Diff for /loncom/interface/lonparmset.pm between versions 1.595 and 1.622

version 1.595, 2020/02/10 19:48:56 version 1.622, 2025/06/28 14:34:46
Line 329  use Apache::lonnavmaps; Line 329  use Apache::lonnavmaps;
 use Apache::longroup;  use Apache::longroup;
 use Apache::lonrss;  use Apache::lonrss;
 use HTML::Entities;  use HTML::Entities;
   use Text::Wrap();
 use LONCAPA qw(:DEFAULT :match);  use LONCAPA qw(:DEFAULT :match);
   
   
Line 978  sub storeparm_by_symb_inner { Line 979  sub storeparm_by_symb_inner {
 # @param {string} $type - the parameter type  # @param {string} $type - the parameter type
 # @param {boolean} $editable - Set to true to get an icon when no value is defined.  # @param {boolean} $editable - Set to true to get an icon when no value is defined.
 sub valout {  sub valout {
     my ($value,$type,$name,$editable)=@_;      my ($value,$type,$editable)=@_;
     my $result = '';      my $result = '';
     # Values of zero are valid.      # Values of zero are valid.
     if (! $value && $value ne '0') {      if (! $value && $value ne '0') {
Line 991  sub valout { Line 992  sub valout {
             $result=' ';              $result=' ';
         }          }
     } else {      } else {
         if ($type eq 'date_interval') {          if (($type eq 'date_interval') || ($type eq 'string_grace')) {
             my ($totalsecs,$donesuffix) = split(/_/,$value,2);              if ($type eq 'string_grace') {
             my ($usesdone,$donebuttontext,$proctor,$secretkey);                  my @items;
             if ($donesuffix =~ /^done\:([^\:]+)\:(.*)$/) {                  if ($value =~ /,/) {
                 $donebuttontext = $1;                      @items = split(/,/,$value);
                 (undef,$proctor,$secretkey) = split(/_/,$2);  
                 $usesdone = 'done';  
             } elsif ($donesuffix =~ /^done(|_.+)$/) {  
                 $donebuttontext = &mt('Done');  
                 ($usesdone,$proctor,$secretkey) = split(/_/,$donesuffix);  
             }  
             my ($sec,$min,$hour,$mday,$mon,$year)=gmtime($totalsecs);  
             my @timer;  
             $year=$year-70;  
             $mday--;  
             if ($year) {  
 #               $result.=&mt('[quant,_1,yr]',$year).' ';  
                 push(@timer,&mt('[quant,_1,yr]',$year));  
             }  
             if ($mon) {  
 #               $result.=&mt('[quant,_1,mth]',$mon).' ';  
                 push(@timer,&mt('[quant,_1,mth]',$mon));  
             }  
             if ($mday) {  
 #               $result.=&mt('[quant,_1,day]',$mday).' ';  
                 push(@timer,&mt('[quant,_1,day]',$mday));  
             }  
             if ($hour) {  
 #               $result.=&mt('[quant,_1,hr]',$hour).' ';  
                 push(@timer,&mt('[quant,_1,hr]',$hour));  
             }  
             if ($min) {  
 #               $result.=&mt('[quant,_1,min]',$min).' ';  
                 push(@timer,&mt('[quant,_1,min]',$min));  
             }  
             if ($sec) {  
 #               $result.=&mt('[quant,_1,sec]',$sec).' ';  
                 push(@timer,&mt('[quant,_1,sec]',$sec));  
             }  
 #           $result=~s/\s+$//;  
             if (!@timer) { # Special case: all entries 0 -> display "0 secs" intead of empty field to keep this field editable  
                 push(@timer,&mt('[quant,_1,sec]',0));  
             }  
             $result.=join(", ",@timer);  
             if ($usesdone eq 'done') {  
                 if ($secretkey) {  
                     $result .= ' '.&mt('+ "[_1]" with proctor key: [_2]',$donebuttontext,$secretkey);    
                 } else {                  } else {
                     $result .= ' + "'.$donebuttontext.'"';                      @items = ($value);
                   }
                   foreach my $item (@items) {
                       if ($item =~ /^\d+:(0|1)\.?\d*:(0|1)$/) {
                           my ($totalsecs,$fraction,$grad) = split(/:/,$item);
                           $result .= &interval_to_humanstr($totalsecs);
                           if (($fraction >=0) && ($fraction <=1)) {
                               $result .= '&nbsp;|&nbsp;'.$fraction.'&nbsp;'.&mt('pts');
                               if ($grad == 1) {
                                   $result .= '&nbsp;('.&mt('gradual').')';
                               }
                           }
                           $result .= ', ';
                       }
                   }
                   $result =~ s/, $//;
               } else {
                   my ($totalsecs,$donesuffix) = split(/_/,$value,2);
                   $result = &interval_to_humanstr($totalsecs);
                   my ($usesdone,$donebuttontext,$proctor,$secretkey);
                   if ($donesuffix =~ /^done\:([^\:]+)\:(.*)$/) {
                       $donebuttontext = $1;
                       (undef,$proctor,$secretkey) = split(/_/,$2);
                       $usesdone = 'done';
                   } elsif ($donesuffix =~ /^done(|_.+)$/) {
                       $donebuttontext = &mt('Done');
                       ($usesdone,$proctor,$secretkey) = split(/_/,$donesuffix);
                   }
                   if ($usesdone eq 'done') {
                       if ($secretkey) {
                           $result .= ' '.&mt('+ "[_1]" with proctor key: [_2]',$donebuttontext,$secretkey);
                       } else {
                           $result .= ' + "'.$donebuttontext.'"';
                       }
                 }                  }
             }              }
         } elsif (&isdateparm($type)) {          } elsif (&isdateparm($type)) {
Line 1054  sub valout { Line 1046  sub valout {
     return $result;      return $result;
 }  }
   
   sub interval_to_humanstr {
       my ($totalsecs) = @_;
       my ($sec,$min,$hour,$mday,$mon,$year)=gmtime($totalsecs);
       my @timer;
       $year=$year-70;
       $mday--;
       if ($year) {
           push(@timer,&mt('[quant,_1,yr]',$year));
       }
       if ($mon) {
           push(@timer,&mt('[quant,_1,mth]',$mon));
       }
       if ($mday) {
           push(@timer,&mt('[quant,_1,day]',$mday));
       }
       if ($hour) {
           push(@timer,&mt('[quant,_1,hr]',$hour));
       }
       if ($min) {
           push(@timer,&mt('[quant,_1,min]',$min));
       }
       if ($sec) {
           push(@timer,&mt('[quant,_1,sec]',$sec));
       }
       if (!@timer) { # Special case: all entries 0 -> display "0 secs" intead of empty field to keep this field editable
           push(@timer,&mt('[quant,_1,sec]',0));
       }
       return '<span style="white-space:nowrap">'.join('</span>, <span style="white-space:nowrap">',@timer).'</span>';
   }
   
 # Returns HTML containing a link on a parameter value, for table mode.  # Returns HTML containing a link on a parameter value, for table mode.
 # The link uses the javascript function 'pjump'.  # The link uses the javascript function 'pjump'.
Line 1241  function validateParms() { Line 1262  function validateParms() {
     var tailLenient = /\.lenient$/;      var tailLenient = /\.lenient$/;
     var patternRelWeight = /^\-?[\d.]+$/;      var patternRelWeight = /^\-?[\d.]+$/;
     var patternLenientStd = /^(yes|no|default)$/;      var patternLenientStd = /^(yes|no|default)$/;
       var ipRegExp = /^setip/;
     var ipallowRegExp = /^setipallow_/;      var ipallowRegExp = /^setipallow_/;
     var ipdenyRegExp = /^setipdeny_/;       var ipdenyRegExp = /^setipdeny_/; 
     var deeplinkRegExp = /^deeplink_(listing|scope)_/;      var graceRegExp = /^setgrace_/;
     var deeplinkUrlsRegExp = /^deeplink_urls_/;      var deeplinkRegExp = /^deeplink_/;
     var deeplinkltiRegExp = /^deeplink_lti_/;      var dlListScopeRegExp = /^deeplink_(state|others|listing|scope)_/; 
     var deeplinkkeyRegExp = /^deeplink_key_/;      var dlLinkProtectRegExp = /^deeplink_protect_/;
       var dlLtidRegExp = /^deeplink_ltid_/;
       var dlLticRegExp = /^deeplink_ltic_/;
       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\-]+/;      var patternIP = /[\[\]\*\.a-zA-Z\d\-]+/;
     if ((document.parmform.elements.length != 'undefined')  && (document.parmform.elements.length) != 'null') {      var numelements = document.parmform.elements.length;
         if (document.parmform.elements.length) {      if ((typeof(numelements) != 'undefined') && (numelements != null)) {
             for (i=0; i<document.parmform.elements.length; i++) {          if (numelements) {
               for (i=0; i<numelements; i++) {
                 var name=document.parmform.elements[i].name;                  var name=document.parmform.elements[i].name;
                 if (textRegExp.test(name)) {                  if (textRegExp.test(name)) {
                     var identifier = name.replace(textRegExp,'');                      var identifier = name.replace(textRegExp,'');
Line 1275  function validateParms() { Line 1306  function validateParms() {
                             }                              }
                         }                          }
                     }                      }
                 } else if (ipallowRegExp.test(name)) {                  } else if (ipRegExp.test(name)) {
                     var identifier = name.replace(ipallowRegExp,'');                      if (ipallowRegExp.test(name)) {
                     var possallow = document.parmform.elements[i].value;                          var identifier = name.replace(ipallowRegExp,'');
                     possallow = possallow.replace(/^\s+|\s+$/g,'');                          var possallow = document.parmform.elements[i].value;
                     if (patternIP.test(possallow)) {                          possallow = possallow.replace(/^\s+|\s+$/g,'');
                         if (document.parmform.elements['set_'+identifier].value) {                          if (patternIP.test(possallow)) {
                             possallow = ','+possallow;                              if (document.parmform.elements['set_'+identifier].value) {
                         }                                  possallow = ','+possallow;
                         document.parmform.elements['set_'+identifier].value += possallow;                              }
                     }                              document.parmform.elements['set_'+identifier].value += possallow;
                 } else if (ipdenyRegExp.test(name)) {                          }
                     var identifier = name.replace(ipdenyRegExp,'');                      } else if (ipdenyRegExp.test(name)) {
                     var possdeny = document.parmform.elements[i].value;                          var identifier = name.replace(ipdenyRegExp,'');
                     possdeny = possdeny.replace(/^\s+|\s+$/g,'');                          var possdeny = document.parmform.elements[i].value;
                     if (patternIP.test(possdeny)) {                          possdeny = possdeny.replace(/^\s+|\s+$/g,'');
                         possdeny = '!'+possdeny;                          if (patternIP.test(possdeny)) {
                         if (document.parmform.elements['set_'+identifier].value) {                              possdeny = '!'+possdeny;
                             possdeny = ','+possdeny;                              if (document.parmform.elements['set_'+identifier].value) {
                                   possdeny = ','+possdeny;
                               }
                               document.parmform.elements['set_'+identifier].value += possdeny;
                         }                          }
                         document.parmform.elements['set_'+identifier].value += possdeny;  
                     }                      }
                 } else if (deeplinkRegExp.test(name)) {                  } else if (deeplinkRegExp.test(name)) {
                     var identifier =  name.replace(deeplinkRegExp,'');                      if (dlListScopeRegExp.test(name)) {
                     var possdeeplink = document.parmform.elements[i].value;                          var identifier =  name.replace(dlListScopeRegExp,'');
                     possdeeplink = possdeeplink.replace(/^\s+|\s+$/g,'');                          var idx = document.parmform.elements[i].selectedIndex;
                     if (document.parmform.elements['set_'+identifier].value) {                          if (idx > 0) { 
                         possdeeplink = ','+possdeeplink;                              var possdeeplink = document.parmform.elements[i].options[idx].value
                               possdeeplink = possdeeplink.replace(/^\s+|\s+$/g,'');
                               if (document.parmform.elements['set_'+identifier].value) {
                                   possdeeplink = ','+possdeeplink;
                               }
                               document.parmform.elements['set_'+identifier].value += possdeeplink;
                           }
                       } else if (dlLinkProtectRegExp.test(name)) {
                           if (document.parmform.elements[i].checked) {
                               var identifier =  name.replace(dlLinkProtectRegExp,'');
                               var posslinkurl = document.parmform.elements[i].value;
                               posslinkurl = posslinkurl.replace(/^\s+|\s+$/g,'');
                               if (document.parmform.elements['set_'+identifier].value) {
                                   posslinkurl = ','+posslinkurl;
                               }
                               document.parmform.elements['set_'+identifier].value += posslinkurl;
                           }
                       } else if (dlLtidRegExp.test(name)) {
                           var identifier = name.replace(dlLtidRegExp,'');
                           if (isRadioSet('deeplink_protect_'+identifier,'ltid')) {
                               var possltid = document.parmform.elements[i].value;
                               possltid = possltid.replace(/\D+/g,'');
                               if (possltid.length) {
                                   if (document.parmform.elements['set_'+identifier].value) {
                                       possltid = ':'+possltid;
                                   }
                                   document.parmform.elements['set_'+identifier].value += possltid;
                               } else {
                                   document.parmform.elements['set_'+identifier].value = '';
                                   alert("A link type of 'domain LTI launch' was selected but no domain LTI launcher was selected.\nPlease select one, or choose a different supported link type.");
                                   return false;  
                               }
                           }
                       } else if (dlLticRegExp.test(name)) {
                           var identifier = name.replace(dlLticRegExp,'');
                           if (isRadioSet('deeplink_protect_'+identifier,'ltic')) {
                               var possltic = document.parmform.elements[i].value;
                               possltic = possltic.replace(/\D+/g,'');
                               if (possltic.length) {
                                   if (document.parmform.elements['set_'+identifier].value) {
                                       possltic = ':'+possltic;
                                   }
                                   document.parmform.elements['set_'+identifier].value += possltic;
                               } else {
                                   document.parmform.elements['set_'+identifier].value = '';
                                   alert("A link type of 'course LTI launch' was selected but no course LTI launcher was selected.\nPlease select one, or choose a different supported link type.");
                                   return false;
                               }
                           }
                       } else if (dlKeyRegExp.test(name)) {
                           var identifier = name.replace(dlKeyRegExp,'');
                           if (isRadioSet('deeplink_protect_'+identifier,'key')) {
                               var posskey = document.parmform.elements[i].value;
                               posskey = posskey.replace(/^\s+|\s+$/g,'');
                               var origlength = posskey.length;
                               posskey = posskey.replace(/[^a-zA-Z\d_.!@#$%^&*()+=-]/g,'');
                               var newlength = posskey.length;
                               if (newlength > 0) {
                                   var change = origlength - newlength;
                                   if (change) {
                                       alert(change+' disallowed character(s) removed from deeplink key'); 
                                   }
                                   if (document.parmform.elements['set_'+identifier].value) {
                                       posskey = ':'+posskey;
                                   }
                                   document.parmform.elements['set_'+identifier].value += posskey;
                               } else {
                                   document.parmform.elements['set_'+identifier].value = '';
                                   if (newlength < origlength) {
                                       alert("A link type of 'deep with key' was selected but the key value was blank, after removing disallowed characters.\nPlease enter a key using one or more of: a-zA-Z0-9_.!@#$%^&*()+=-");
                                   } else {
                                       alert("A link type of 'deep with key' was selected but the key value was blank.\nPlease enter a key.");
                                   }
                                   return false;
                               }
                           }
                       } else if (dlMenusRegExp.test(name)) {
                           if (document.parmform.elements[i].checked) {
                               var identifier =  name.replace(dlMenusRegExp,'');
                               var posslinkmenu = document.parmform.elements[i].value;
                               posslinkmenu = posslinkmenu.replace(/^\s+|\s+$/g,'');
                               if (posslinkmenu == 'std') {
                                   posslinkmenu = '0';
                                   if (document.parmform.elements['set_'+identifier].value) {
                                       posslinkmenu = ','+posslinkmenu;
                                   }
                                   document.parmform.elements['set_'+identifier].value += posslinkmenu;
                               }
                           }
                       } else if (dlCollsRegExp.test(name)) {
                           var identifier =  name.replace(dlCollsRegExp,'');
                           if (isRadioSet('deeplink_menus_'+identifier,'colls')) {
                               var posslinkmenu = document.parmform.elements[i].value;
                               if (document.parmform.elements['set_'+identifier].value) {
                                   posslinkmenu = ','+posslinkmenu;
                               }
                               document.parmform.elements['set_'+identifier].value += posslinkmenu;
                           }
                       } else if (dlTargetRegExp.test(name)) {
                           var identifier =  name.replace(dlTargetRegExp,'');
                           var idx = document.parmform.elements[i].selectedIndex;
                           if (idx > 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;
                               }
                           }
                     }                      }
                     document.parmform.elements['set_'+identifier].value += possdeeplink;                  } else if (graceRegExp.test(name)) {
                 } else if (deeplinkUrlsRegExp.test(name)) {                      var identifier = name.replace(graceRegExp,'');
                     if (document.parmform.elements[i].checked) {                      var divElem = document.parmform.elements[i].closest('div'); 
                         var identifier =  name.replace(deeplinkUrlsRegExp,'');                      var timeSels = divElem.getElementsByTagName("select");
                         var posslinkurl = document.parmform.elements[i].value;                      var total = 0;
                         posslinkurl = posslinkurl.replace(/^\s+|\s+$/g,'');                      if (timeSels.length) {
                         if (document.parmform.elements['set_'+identifier].value) {                           for (var j=0; j<timeSels.length; j++) {
                             posslinkurl = ','+posslinkurl;                              var sname = timeSels[j].getAttribute('name');
                         }                              var poss = parseInt(timeSels[j].options[timeSels[j].selectedIndex].value);
                         document.parmform.elements['set_'+identifier].value += posslinkurl;                              if (sname == 'days_'+identifier) {
                     }                                  if ((poss > 0) && (poss <= 31)) {
                 } else if (deeplinkltiRegExp.test(name)) {                                      total += (poss * 86400); 
                     var identifier = name.replace(deeplinkltiRegExp,'');                                  }
                     var posslti = document.parmform.elements[i].value;                              } else if (sname == 'hours_'+identifier) {
                     posslti = posslti.replace(/\D+/g,'');                                  if ((poss > 0) && (poss < 24)) {
                     if (document.parmform.elements['set_'+identifier].value) {                                      total += (poss * 3600);
                         posslti = ':'+posslti;                                  }
                               } else if (sname == 'minutes_'+identifier) {
                                   if ((poss > 0) && (poss < 60)) {
                                       total += (poss * 60);
                                   }
                               } else if (sname == 'seconds_'+identifier) {
                                   if ((poss > 0) && (poss < 60)) {
                                       total += poss;
                                   }
                               }
                           }
                       }
                       var inputElems = divElem.getElementsByTagName("input");
                       var frac = '';
                       var grad = '';
                       if (inputElems.length) {
                           for (var j=0; j<inputElems.length; j++) {
                               var iname = inputElems[j].getAttribute('name');
                               if (iname == 'frac_'+identifier) {
                                   var ival = inputElems[j].value;
                                   ival.trim();
                                   var poss = parseFloat(ival);
                                   if ((typeof poss === 'number') && (!isNaN(poss))) {
                                       if ((poss => 0) && (poss <= 1)) {
                                           frac = poss;
                                       }
                                   }
                               } else if (iname == 'grad_'+identifier) {
                                   if (inputElems[j].checked) {
                                       grad = 1;
                                   } else {
                                       grad = 0;
                                   }
                               }
                           }
                     }                      }
                     document.parmform.elements['set_'+identifier].value += posslti;                      document.parmform.elements[i].value = total+':'+frac+':'+grad;
                 } else if (deeplinkkeyRegExp.test(name)) {  
                     var identifier = name.replace(deeplinkkeyRegExp,'');  
                     var posskey = document.parmform.elements[i].value;  
                     posskey = posskey.replace(/\W+/g,'');  
                     if (document.parmform.elements['set_'+identifier].value) {                      if (document.parmform.elements['set_'+identifier].value) {
                         posslti = ':'+posskey;                          document.parmform.elements['set_'+identifier].value += ',';
                     }                      }
                     document.parmform.elements['set_'+identifier].value += posskey;                      document.parmform.elements['set_'+identifier].value += document.parmform.elements[i].value;
                 }                  }
             }              }
         }          }
Line 1337  function validateParms() { Line 1546  function validateParms() {
     return true;      return true;
 }  }
   
   function isRadioSet(name,expected) {
       var menuitems = document.getElementsByName(name);
       var radioLength = menuitems.length;
       result = false;
       if (radioLength  > 1) {
           for (var j=0; j<radioLength; j++) {
               if (menuitems[j].checked) {
                   if (menuitems[j].value == expected) {
                       result = true;
                       break;
                   }
               }
           }
       }
       return result;
   }
   
 ENDSCRIPT  ENDSCRIPT
 }  }
   
Line 1365  sub ipacc_boxes_js  { Line 1591  sub ipacc_boxes_js  {
 END  END
 }  }
   
   sub grace_js {
       my %lt = &grace_titles();
       &js_escape(\%lt);
       my $overdue = '<fieldset class="LC_grace"><legend>'.$lt{'sinc'}.'</legend>';
       foreach my $which (['days', 86400, 31],
                          ['hours', 3600, 23],
                          ['minutes', 60, 59],
                          ['seconds',  1, 59]) {
           my ($name, $factor, $max) = @{ $which };
           my %select = ((map {$_ => $_} (0..$max)),
                         'select_form_order' => [0..$max]);
           my $selector = &Apache::loncommon::select_form('',$name."_'+identifier+'",
                                                          \%select);
           $selector =~ s/([\r\n\f]+)//g;
           $overdue .= $selector.'&nbsp;'.$lt{$name}.('&nbsp;'x2).' ';
       }
       $overdue .= '</fieldset>';
       return <<"END";
   \$(document).ready(function() {
       var wrapper         = \$(".LC_string_grace_wrap");
       var add_button      = \$(".LC_add_grace_button");
       var graceRegExp     = /^LC_string_grace_/;
   
       \$(add_button).click(function(e){
           e.preventDefault();
           var identifier = \$(this).closest("div").attr("id");
           identifier = identifier.replace(graceRegExp,'');
           \$(this).closest('div').find('.LC_string_grace_inner').append('<div><input type="hidden" name="setgrace_'+identifier+'" value="" />$overdue<fieldset class="LC_grace"><legend>$lt{scor}</legend><input type="text" size="3" name="frac_'+identifier+'" value="" />&nbsp;&nbsp;<label><input type="checkbox" value="1" name="grad_'+identifier+'" />$lt{grad}</label></fieldset><a href="#" class="LC_remove_grace">$lt{remo}</a></div>');
       });
   
       \$(wrapper).delegate(".LC_remove_grace","click", function(e){
           e.preventDefault(); \$(this).closest("div").remove();
       })
   });
   
   
   END
   }
   
 # Javascript function toggleSecret, for overview mode.  # Javascript function toggleSecret, for overview mode.
 sub done_proctor_js {  sub done_proctor_js {
       my $defaultdone = &mt('Done');
       &js_escape(\$defaultdone);
     return <<"END";      return <<"END";
 function toggleSecret(form,radio,key) {  function toggleSecret(form,radio,key) {
     var radios = form[radio+key];      var radios = form[radio+key];
Line 1383  function toggleSecret(form,radio,key) { Line 1650  function toggleSecret(form,radio,key) {
                         document.getElementById('done_'+key+'_proctorkey').value='';                          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';
                           }
                       }
                   }
             }              }
         }          }
     }      }
Line 1401  function toggleDeepLink(form,item,key) { Line 1677  function toggleDeepLink(form,item,key) {
         if (document.getElementById('deeplink_key_'+item+'_'+key)) {          if (document.getElementById('deeplink_key_'+item+'_'+key)) {
             keybox = document.getElementById('deeplink_key_'+item+'_'+key);              keybox = document.getElementById('deeplink_key_'+item+'_'+key);
         }          }
         var ltidiv;          var divoptions = new Array();
         if (document.getElementById('deeplinkdiv_lti_'+item+'_'+key)) {          if (item == 'protect') {
             ltidiv = document.getElementById('deeplinkdiv_lti_'+item+'_'+key);              divoptions = ['ltic','ltid'];
           } else {
               if (item == 'menus') {
                   divoptions = ['colls'];
               }
           }
           var seldivs = new Array();
           if ((item == 'protect') || (item == 'menus')) {
               for (var i=0; i<divoptions.length; i++) {
                   if (document.getElementById('deeplinkdiv_'+divoptions[i]+'_'+item+'_'+key)) {
                       seldivs[i] = document.getElementById('deeplinkdiv_'+divoptions[i]+'_'+item+'_'+key);
                   } else {
                       seldivs[i] = '';
                   }
               }
         }          }
         for (var i=0; i<radios.length; i++) {          for (var i=0; i<radios.length; i++) {
             if (radios[i].checked) {              if (radios[i].checked) {
                 if (radios[i].value == 'lti') {                  if ((item == 'protect') || (item == 'menus')) {
                     ltidiv.style.display = 'inline-block';                      for (var j=0; j<seldivs.length; j++) {
                     keybox.type = 'hidden';                          if (radios[i].value == divoptions[j]) {
                     keybox.value = '';                              if (seldivs[j] != '') {
                 } else {                                  seldivs[j].style.display = 'inline-block';
                     if (ltidiv != '') {                              }
                         ltidiv.style.display = 'none';                              if (item == 'protect') {
                         form['deeplink_lti_'+key].selectedIndex = 0;                                  keybox.type = 'hidden';
                                   keybox.value = '';
                               }
                           } else {
                               if (seldivs[j] != '') {
                                   seldivs[j].style.display = 'none';
                                   form['deeplink_'+divoptions[j]+'_'+key].selectedIndex = 0;
                               }
                           }
                     }                      }
                     if (radios[i].value == 'key') {                      if (item == 'protect') {
                         keybox.type = 'text';                          if (radios[i].value == 'key') {
                     } else {                              keybox.type = 'text';
                         keybox.type = 'hidden';                          } else {
                               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';
                                   }
                               }
                           }
                     }                      }
                 }                  }
             }              }
Line 1549  sub print_row { Line 1867  sub print_row {
     if ($automatic) {      if ($automatic) {
         $parm.='<span class="LC_warning"><br />'.&mt('Automatically sets').' '.join(', ',split(/\:/,$automatic)).'</span>';          $parm.='<span class="LC_warning"><br />'.&mt('Automatically sets').' '.join(', ',split(/\:/,$automatic)).'</span>';
     }      }
       my $advice;
       if ((ref($name) eq 'HASH') && ($name->{$which} eq 'mapalias') &&
           (ref($symbp) eq 'HASH') && ($parmlev eq 'full')) {
           if ($symbp->{$rid} =~ m{^uploaded/}) {
               if ($result == 14) {
                   $advice = &mt('Use Course Editor to modify this.');
               } else {
                   $advice = &mt('Use Course Editor to set this.');
               }
           } else {
               if ($result == 14) {
                   $advice = &mt('Use Resource Assembly Tool to modify this.');
               } else {
                   $advice = &mt('Use Resource Assembly Tool to set this.');
               }
           }
           $parm .= '<br /><span class="LC_fontsize_small LC_cusr_emph">'.$advice.'</span>';
       }
     $r->print('<td>'.$parm.'</td>');      $r->print('<td>'.$parm.'</td>');
   
     my $thismarker=$which;      my $thismarker=$which;
Line 1615  sub print_row { Line 1951  sub print_row {
         $effparm_rec = 1;          $effparm_rec = 1;
     }      }
     if ($parmname eq 'deeplink') {      if ($parmname eq 'deeplink') {
         my %posslti;          my ($domltistr,$crsltistr);
         my %lti =          my %lti =
             &Apache::lonnet::get_domain_lti($env{'course.'.$env{'request.course.id'}.'.domain'},              &Apache::lonnet::get_domain_lti($env{'course.'.$env{'request.course.id'}.'.domain'},
                                             'provider');                                              'linkprot');
         foreach my $item (keys(%lti)) {          if (keys(%lti)) {
             if (ref($lti{$item}) eq 'HASH') {              foreach my $item (sort { $a <=> $b }  (keys(%lti))) {
                 unless ($lti{$item}{'requser'}) {                  if (($item =~ /^\d+$/) && (ref($lti{$item}) eq 'HASH')) {
                     $posslti{$item} = $lti{$item}{'consumer'};                      $domltistr .= $item.':'.&escape(&escape($lti{$item}{'name'})).',';
                   }
               }
               $domltistr =~ s/,$//;
               if ($domltistr) {
                   $extra = 'ltid_'.$domltistr;
               }
           }
           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')) {
                       $crsltistr .= $item.':'.&escape(&escape($courselti{$item}{'name'})).',';
                 }                  }
             }              }
               $crsltistr =~ s/,$//;
               if ($crsltistr) {
                   if ($extra) {
                       $extra .= '&';
                   }
                   $extra .= 'ltic_'.$crsltistr;
               }
         }          }
         if (keys(%posslti)) {          if ($env{'course.'.$env{'request.course.id'}.'.menucollections'}) {
             $extra = 'lti_';              my @colls;
             foreach my $lti (sort { $a <=> $b } keys(%posslti)) {              foreach my $item (split(/;/,$env{'course.'.$env{'request.course.id'}.'.menucollections'})) {
                 $extra .= $lti.':'.&js_escape($posslti{$lti}).',';                  my ($num,$value) = split(/\%/,$item);
                   if ($num =~ /^\d+$/) {
                       push(@colls,$num);
                   }
               }
               if (@colls) {
                   if ($extra) {
                       $extra .= '&';
                   }
                   $extra .= 'menus_'.join(',',@colls);
             }              }
             $extra =~ s/,$//;  
         }          }
     }      }
     if ($parmlev eq 'general') {      if ($parmlev eq 'general') {
Line 1766  sub print_row { Line 2129  sub print_row {
 # @param {boolean} $noeditgrp - true if no edit is allowed for group level parameters  # @param {boolean} $noeditgrp - true if no edit is allowed for group level parameters
 # @param {boolean} $readonly -true if editing not allowed.  # @param {boolean} $readonly -true if editing not allowed.
 # @param {boolean} $ismaplevel - true if level is for a map.  # @param {boolean} $ismaplevel - true if level is for a map.
 # @param {strring} $extra - extra informatio to pass to plink.  # @param {string} $extra - extra information to pass to plink.
 sub print_td {  sub print_td {
     my ($r,$which,$defbg,$result,$outpar,$mprefix,$value,$typeoutpar,$display,      my ($r,$which,$defbg,$result,$outpar,$mprefix,$value,$typeoutpar,$display,
         $noeditgrp,$readonly,$ismaplevel,$extra)=@_;          $noeditgrp,$readonly,$ismaplevel,$extra)=@_;
Line 1808  sub print_td { Line 2171  sub print_td {
                 $nolink = 1;                  $nolink = 1;
             }              }
         } elsif ($mprefix =~ /availablestudent\&$/) {          } elsif ($mprefix =~ /availablestudent\&$/) {
             if ($which > 4) {              $nolink = 1;
                 $nolink = 1;  
             }  
         } elsif ($mprefix =~ /examcode\&$/) {          } elsif ($mprefix =~ /examcode\&$/) {
             unless ($which == 2) {              unless ($which == 2) {
                 $nolink = 1;                  $nolink = 1;
Line 1931  sub parm_control_group { Line 2292  sub parm_control_group {
 # @param {hash reference} $uris - hash resource/map id -> resource src  # @param {hash reference} $uris - hash resource/map id -> resource src
 # @param {hash reference} $keyorder - hash parameter key -> appearance rank for this parameter when looking through every resource and every parameter, starting at 100 (integer)  # @param {hash reference} $keyorder - hash parameter key -> appearance rank for this parameter when looking through every resource and every parameter, starting at 100 (integer)
 # @param {hash reference} $defkeytype - hash parameter name -> parameter type  # @param {hash reference} $defkeytype - hash parameter name -> parameter type
   # @param {string} $pssymb - resource symb (when a single resource is selected)
 sub extractResourceInformation {  sub extractResourceInformation {
     my $ids = shift;      my $ids = shift;
     my $typep = shift;      my $typep = shift;
Line 1944  sub extractResourceInformation { Line 2306  sub extractResourceInformation {
     my $uris=shift;      my $uris=shift;
     my $keyorder=shift;      my $keyorder=shift;
     my $defkeytype=shift;      my $defkeytype=shift;
       my $pssymb=shift;
   
     my $keyordercnt=100;      my $keyordercnt=100;
   
     my $navmap = Apache::lonnavmaps::navmap->new();      my $navmap = Apache::lonnavmaps::navmap->new();
     my @allres=$navmap->retrieveResources(undef,undef,1,undef,1);      return unless(ref($navmap));
       my @allres;
       if ($pssymb ne '') {
           my $res = $navmap->getBySymb($pssymb);
           if (ref($res)) {
               @allres = ($res);
           }
       }
       if (!@allres) { 
           @allres=$navmap->retrieveResources(undef,undef,1,undef,1);
       }
     foreach my $resource (@allres) {      foreach my $resource (@allres) {
         my $id=$resource->id();          my $id=$resource->id();
         my ($mapid,$resid)=split(/\./,$id);          my ($mapid,$resid)=split(/\./,$id);
Line 2072  sub isdateparm { Line 2445  sub isdateparm {
   
 sub is_specialstring {  sub is_specialstring {
     my $type=shift;      my $type=shift;
     return (($type=~/^string_/) && (($type ne 'string_yesno')));      return (($type=~/^string_/) && ($type ne 'string_yesno'));
 }  }
   
 # Prints the HTML and Javascript to select parameters, with various shortcuts.  # Prints the HTML and Javascript to select parameters, with various shortcuts.
Line 2185  sub lookUpTableParameter { Line 2558  sub lookUpTableParameter {
         'opendate' => 'time_settings',          'opendate' => 'time_settings',
         'duedate' => 'time_settings',          'duedate' => 'time_settings',
         'answerdate' => 'time_settings',          'answerdate' => 'time_settings',
           'grace' => 'time_settings',
         'interval' => 'time_settings',          'interval' => 'time_settings',
         'contentopen' => 'time_settings',          'contentopen' => 'time_settings',
         'contentclose' => 'time_settings',          'contentclose' => 'time_settings',
Line 2226  sub lookUpTableParameter { Line 2600  sub lookUpTableParameter {
         'lenient' => 'grading',          'lenient' => 'grading',
         'retrypartial' => 'tries',          'retrypartial' => 'tries',
         'discussvote'  => 'misc',          'discussvote'  => 'misc',
           'texdisplay' => 'misc',
         'examcode' => 'high_level_randomization',          'examcode' => 'high_level_randomization',
     );      );
 }  }
Line 2315  sub parmboxes { Line 2690  sub parmboxes {
         &whatIsMyCategory($tempparameter, \%categoryList);          &whatIsMyCategory($tempparameter, \%categoryList);
     }      }
     #part to print the parm-list      #part to print the parm-list
       $Text::Wrap::columns=60;
       $Text::Wrap::separator='<br />';
     foreach my $key (sort { $category_order{$a} <=> $category_order{$b} } keys(%categoryList)) {      foreach my $key (sort { $category_order{$a} <=> $category_order{$b} } keys(%categoryList)) {
         next if (@{$categoryList{$key}} == 0);          next if (@{$categoryList{$key}} == 0);
         next if ($key eq '');          next if ($key eq '');
Line 2328  sub parmboxes { Line 2705  sub parmboxes {
             if ($$pscat[0] eq "all" || grep $_ eq $tempkey, @{$pscat}) {              if ($$pscat[0] eq "all" || grep $_ eq $tempkey, @{$pscat}) {
                 $r->print( ' checked="checked"');                  $r->print( ' checked="checked"');
             }              }
             $r->print(' />'.($$allparms{$tempkey}=~/\S/ ? $$allparms{$tempkey}              $r->print(' />'.($$allparms{$tempkey}=~/\S/ ? 
                                                       : $tempkey)                               Text::Wrap::wrap('','&nbsp;'x4,$$allparms{$tempkey})
                                : $tempkey)
                      .'</label></span><br />'."\n");                       .'</label></span><br />'."\n");
         }          }
         $r->print('</div>');          $r->print('</div>');
Line 2420  sub partmenu { Line 2798  sub partmenu {
 sub usermenu {  sub usermenu {
     my ($r,$uname,$id,$udom,$csec,$cgroup,$parmlev,$usersgroups,$pssymb)=@_;      my ($r,$uname,$id,$udom,$csec,$cgroup,$parmlev,$usersgroups,$pssymb)=@_;
     my $chooseopt=&Apache::loncommon::select_dom_form($udom,'udom').' '.      my $chooseopt=&Apache::loncommon::select_dom_form($udom,'udom').' '.
         &Apache::loncommon::selectstudent_link('parmform','uname','udom');                    &Apache::loncommon::selectstudent_link('parmform','uname','udom','condition').
     my $selscript=&Apache::loncommon::studentbrowser_javascript();                    &Apache::lonhtmlcommon::scripttag(<<ENDJS);
   function setCourseadv(form,caller) {
       if (caller.value == 'st') {
           form.courseadv.value = 'none';
       } else {
           form.courseadv.value = '';
       }
       return;
   }
   ENDJS
   
       my (%chkroles,$stuonly,$courseadv);
       if ($env{'form.userroles'} eq 'any') {
           $chkroles{'any'} = ' checked="checked"';
       } else {
           $chkroles{'st'} = ' checked="checked"';
           $courseadv = 'none';
       }
       my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
       if ($crstype eq 'Community') {
           $stuonly = &mt('member only');
       } else {
           $stuonly = &mt('student only');
       }
       $chooseopt .= '<br /><span class="LC_cusr_subheading">'.
                     &mt("User's role").':&nbsp;'.
                     '<label><input type="radio" name="userroles" value="st"'.$chkroles{'st'}.' onclick="setCourseadv(this.form,this);" />'.
                     $stuonly.'</label>&nbsp;&nbsp;'.
                     '<label><input type="radio" name="userroles" value="any"'.$chkroles{'any'}.' onclick="setCourseadv(this.form,this);" />'.
                     &mt('any role').'</label><input type="hidden" id="courseadv" name="courseadv" value="'.$courseadv.'" /></span>';
     my $sections='';      my $sections='';
     my %sectionhash = &Apache::loncommon::get_sections();      my %sectionhash = &Apache::loncommon::get_sections();
   
Line 2489  function group_or_section(caller) { Line 2895  function group_or_section(caller) {
     }      }
   
     if (%grouphash) {      if (%grouphash) {
         $groups=&mt('Group:').' <select name="cgroup"';          $groups=&mt('Group').': <select name="cgroup"';
         if (%sectionhash && $env{'form.action'} eq 'settable' && $currsec eq '') {          if (%sectionhash && $env{'form.action'} eq 'settable' && $currsec eq '') {
             $groups .= qq| onchange="group_or_section('cgroup')" |;              $groups .= qq| onchange="group_or_section('cgroup')" |;
         }          }
Line 2560  sub displaymenu { Line 2966  sub displaymenu {
 # @param {string} $pschp - selected map pc, or 'all'  # @param {string} $pschp - selected map pc, or 'all'
 # @param {hash reference} $maptitles - hash map id or src -> map title  # @param {hash reference} $maptitles - hash map id or src -> map title
 # @param {hash reference} $symbp - hash map pc or resource/map id -> map src.'___(all)' or resource symb  # @param {hash reference} $symbp - hash map pc or resource/map id -> map src.'___(all)' or resource symb
   # @param {string} $parmlev - parameter level (Resource:'full', Map:'map', Course:'general')
 sub mapmenu {  sub mapmenu {
     my ($r,$allmaps,$pschp,$maptitles,$symbp)=@_;      my ($r,$allmaps,$pschp,$maptitles,$symbp,$parmlev)=@_;
     my %allmaps_inverted = reverse %$allmaps;      my %allmaps_inverted = reverse %$allmaps;
     my $navmap = Apache::lonnavmaps::navmap->new();      my $navmap = Apache::lonnavmaps::navmap->new();
     my $tree=[];      my $tree=[];
Line 2609  sub mapmenu { Line 3016  sub mapmenu {
         }          }
     }      }
 # Show it ...      # 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')) {      if ((ref($tree) eq 'ARRAY') && (ref($treeinfo) eq 'HASH')) {
         my $icon = '<img src="/adm/lonIcons/navmap.folder.open.gif" alt="" />';          my $icon = '<img src="/adm/lonIcons/navmap.folder.open.gif" alt="" />';
         my $whitespace =          my $whitespace =
Line 2851  sub keysindisplayorder { Line 3262  sub keysindisplayorder {
 #  #
 # @param {Apache2::RequestRec} $r - the Apache request  # @param {Apache2::RequestRec} $r - the Apache request
 # @param {string} $sortorder - realmstudent|studentrealm  # @param {string} $sortorder - realmstudent|studentrealm
   # @param {string} $context - newoverview|overview
 sub sortmenu {  sub sortmenu {
     my ($r,$sortorder)=@_;      my ($r,$sortorder,$context)=@_;
     $r->print('<br /><label><input type="radio" name="sortorder" value="realmstudent"');      my %text;
     if ($sortorder eq 'realmstudent') {      if ($context eq 'newoverview') {
        $r->print(' checked="checked"');          %text = &Apache::lonlocal::texthash (
                      realmstudent => 'Sort by location in course first, then student (group/section)',
                      studentrealm => 'Sort by student (group/section) first, then location in course',
           );
       } else {
           %text = &Apache::lonlocal::texthash (
                      realmstudent => 'Sort by realm first, then student (group/section)',
                      studentrealm => 'Sort by student (group/section) first, then realm',
           );
     }      }
     $r->print(' />'.&mt('Sort by realm first, then student (group/section)'));      my %sortchecked = (
     $r->print('</label><br /><label><input type="radio" name="sortorder" value="studentrealm"');         realmstudent => ' checked="checked"',
          studentrealm => '',
       );
     if ($sortorder eq 'studentrealm') {      if ($sortorder eq 'studentrealm') {
        $r->print(' checked="checked"');          $sortchecked{'studentrealm'} = $sortchecked{'realmstudent'};
           $sortchecked{'realmstudent'} = '';
       }
       foreach my $sorttype ('realmstudent','studentrealm') {
           $r->print('<br /><label><input type="radio" name="sortorder" value="'.$sorttype.'"'.$sortchecked{$sorttype}.' />'.
                     $text{$sorttype}.'</label>');
     }      }
     $r->print(' />'.&mt('Sort by student (group/section) first, then realm').  
           '</label>');  
 }  }
   
 # Returns a hash parameter key -> order (integer) giving the order for some parameters.  # Returns a hash parameter key -> order (integer) giving the order for some parameters.
Line 2873  sub standardkeyorder { Line 3298  sub standardkeyorder {
     return ('parameter_0_opendate' => 1,      return ('parameter_0_opendate' => 1,
         'parameter_0_duedate' => 2,          'parameter_0_duedate' => 2,
         'parameter_0_answerdate' => 3,          'parameter_0_answerdate' => 3,
         'parameter_0_interval' => 4,          'parameter_0_grace' => 4,
         'parameter_0_weight' => 5,          'parameter_0_interval' => 5,
         'parameter_0_maxtries' => 6,          'parameter_0_weight' => 6,
         'parameter_0_hinttries' => 7,          'parameter_0_maxtries' => 7,
         'parameter_0_contentopen' => 8,          'parameter_0_hinttries' => 8,
         'parameter_0_contentclose' => 9,          'parameter_0_contentopen' => 9,
         'parameter_0_type' => 10,          'parameter_0_contentclose' => 10,
         'parameter_0_problemstatus' => 11,          'parameter_0_type' => 11,
         'parameter_0_hiddenresource' => 12,          'parameter_0_problemstatus' => 12,
         'parameter_0_hiddenparts' => 13,          'parameter_0_hiddenresource' => 13,
         'parameter_0_display' => 14,          'parameter_0_hiddenparts' => 14,
         'parameter_0_ordered' => 15,          'parameter_0_display' => 15,
         'parameter_0_tol' => 16,          'parameter_0_ordered' => 16,
         'parameter_0_sig' => 17,          'parameter_0_tol' => 17,
         'parameter_0_turnoffunit' => 18,          'parameter_0_sig' => 18,
         'parameter_0_discussend' => 19,          'parameter_0_turnoffunit' => 19,
         'parameter_0_discusshide' => 20,          'parameter_0_discussend' => 20,
         'parameter_0_discussvote' => 21,          'parameter_0_discusshide' => 21,
         'parameter_0_printstartdate'  =>  22,          'parameter_0_discussvote' => 22,
         'parameter_0_printenddate' =>  23);          'parameter_0_printstartdate' => 23,
           'parameter_0_printenddate' => 24);
 }  }
   
   
Line 3064  sub assessparms { Line 3490  sub assessparms {
             $csec=&Apache::lonnet::getsection($udom,$uname,              $csec=&Apache::lonnet::getsection($udom,$uname,
                           $env{'request.course.id'});                            $env{'request.course.id'});
             if ($csec eq '-1') {              if ($csec eq '-1') {
                 $message=                  my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
                     '<p class="LC_warning">'.                  if ($env{'form.userroles'} eq 'any') {
                     &mt('User [_1] at domain [_2] not in this course',                      if (($env{'user.name'} eq $uname) && ($env{'user.domain'} eq $udom)) {
                         "'".$uname."'","'".$udom."'").                          $csec = $env{'request.course.sec'};
                     '</p>';                          $message = '<span class="LC_info">';
                 $uname='';                          if ($crstype eq 'Community') {
                 if ($env{'request.course.sec'} ne '') {                              $message .= &mt('User [_1] at domain [_2] has a non-member role in this community',
                     $csec=$env{'request.course.sec'};                                              $uname,$udom);
                           } else {
                               $message .= &mt('User [_1] at domain [_2] has a non-student role in this course',
                                               $uname,$udom);
                           }
                           $message .= '</span>';
                       } else {
                           my @possroles = ('in','ep','ta','cr');
                           if ($crstype eq 'Community') {
                               unshift(@possroles,'co');
                           } else {
                               unshift(@possroles,'cc');
                           }
                           my %not_student_roles =
                               &Apache::lonnet::get_my_roles($uname,$udom,'userroles',['active'],
                                                             \@possroles,[$udom],1,1);
                           my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                           my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
                           my %sections_by_role;
                           foreach my $role (keys(%not_student_roles)) {
                               if ($role =~ /^\Q$cnum:$cdom:\E([^:]+):(|[^:]+)$/) {
                                   my ($rolename,$sec) = ($1,$2);
                                   if ($rolename =~ m{^cr/}) {
                                       $rolename = 'cr';
                                   }
                                   push(@{$sections_by_role{$rolename}},$sec);
                               }
                           }
                           my $numroles = scalar(keys(%sections_by_role));
                           if ($numroles) {
                               foreach my $role (@possroles) {
                                   if (ref($sections_by_role{$role}) eq 'ARRAY') {
                                       my @secs = sort { $a <=> $b } @{$sections_by_role{$role}};
                                       $csec = $secs[0];
                                       last;
                                   }
                               }
                           }
                           if ($csec eq '-1') {
                               $message = '<span class="LC_warning">';
                               if ($crstype eq 'Community') {
                                   $message .= &mt('User [_1] at domain [_2] does not have a role in this community',
                                                   $uname,$udom);
                               } else {
                                   $message .= &mt('User [_1] at domain [_2] does not have a role in this course',
                                                   $uname,$udom);
                               }
                               $message .= '</span>';
                               $uname='';
                               if ($env{'request.course.sec'} ne '') {
                                   $csec=$env{'request.course.sec'};
                               } else {
                                   $csec=$env{'form.csec'};
                               }
                               $cgroup=$env{'form.cgroup'};
                           } else {
                               $message = '<span class="LC_info">';
                               if ($crstype eq 'Community') {
                                   $message .= &mt('User [_1] at domain [_2] has a non-member role in this community',
                                            $uname,$udom);
                               } else {
                                   $message .= &mt('User [_1] at domain [_2] has a non-student role in this course',
                                                   $uname,$udom);
                               }
                               $message .= '</span>';
                           }
                       }
                 } else {                  } else {
                     $csec=$env{'form.csec'};                      $message = '<span class="LC_warning">';
                       if ($crstype eq 'Community') {
                           $message .= &mt('User [_1] at domain [_2] does not have a member role in this community',
                                            $uname,$udom);
                       } else {
                            $message .= &mt('User [_1] at domain [_2] does not have a student role in this course',
                                            $uname,$udom);
                       }
                       $message .= '</span>';
                       $uname='';
                       if ($env{'request.course.sec'} ne '') {
                           $csec=$env{'request.course.sec'};
                       } else {
                           $csec=$env{'form.csec'};
                       }
                       $cgroup=$env{'form.cgroup'};
                 }                  }
                 $cgroup=$env{'form.cgroup'};  
             } elsif ($env{'request.course.sec'} ne '') {              } elsif ($env{'request.course.sec'} ne '') {
                 if ($csec ne $env{'request.course.sec'}) {                  if ($csec ne $env{'request.course.sec'}) {
                     $message='<span class="LC_error">'.                      $message='<span class="LC_warning">'.
                               &mt("User '[_1]' at domain '[_2]' not in section '[_3]'",                                &mt("User '[_1]' at domain '[_2]' not in section '[_3]'",
                                   $uname,$udom,$env{'request.course.sec'}).                                    $uname,$udom,$env{'request.course.sec'}).
                               '</span>';                                '</span>';
Line 3086  sub assessparms { Line 3592  sub assessparms {
                     $csec=$env{'request.course.sec'};                      $csec=$env{'request.course.sec'};
                 }                  }
                 $cgroup=$env{'form.cgroup'};                  $cgroup=$env{'form.cgroup'};
             } else {              }
               if ($uname ne '') {
                 my %name=&Apache::lonnet::userenvironment($udom,$uname,                  my %name=&Apache::lonnet::userenvironment($udom,$uname,
                   ('firstname','middlename','lastname','generation','id'));                    ('firstname','middlename','lastname','generation','id'));
                 $message="\n<p>\n".&mt("Full Name").": ".                  $message .= "\n<p>\n".&mt('Full Name').': '
                 $name{'firstname'}.' '.$name{'middlename'}.' '                              .$name{'firstname'}.' '.$name{'middlename'}.' '
                 .$name{'lastname'}.' '.$name{'generation'}.                              .$name{'lastname'}.' '.$name{'generation'}
                 "<br />\n".&mt('Student/Employee ID').": ".$name{'id'}.'<p>';                              ."<br />\n".&mt('Student/Employee ID').': '.$name{'id'}.'</p>';
             }                  @usersgroups = &Apache::lonnet::get_users_groups(
             @usersgroups = &Apache::lonnet::get_users_groups(                                     $udom,$uname,$env{'request.course.id'});
                                        $udom,$uname,$env{'request.course.id'});                  if (@usersgroups > 0) {
             if (@usersgroups > 0) {                      unless (grep(/^\Q$cgroup\E$/,@usersgroups)) {
                 unless (grep(/^\Q$cgroup\E$/,@usersgroups)) {                          $cgroup = $usersgroups[0];
                     $cgroup = $usersgroups[0];                      }
                   } else {
                       $cgroup = '';
                 }                  }
             }              }
         }          }
Line 3110  sub assessparms { Line 3619  sub assessparms {
 # --------------------------------------------------------- Get all assessments  # --------------------------------------------------------- Get all assessments
     &extractResourceInformation(\@ids, \%typep,\%keyp, \%allparms, \%allparts, \%allmaps,      &extractResourceInformation(\@ids, \%typep,\%keyp, \%allparms, \%allparts, \%allmaps,
                 \%mapp, \%symbp,\%maptitles,\%uris,                  \%mapp, \%symbp,\%maptitles,\%uris,
                 \%keyorder);                  \%keyorder,undef,$pssymb);
   
     %allmaps_inverted = reverse(%allmaps);      %allmaps_inverted = reverse(%allmaps);
   
Line 3127  sub assessparms { Line 3636  sub assessparms {
         my $chome = $env{'course.'.$env{'request.course.id'}.'.home'};          my $chome = $env{'course.'.$env{'request.course.id'}.'.home'};
         my ($got_chostname,$chostname,$cmajor,$cminor);          my ($got_chostname,$chostname,$cmajor,$cminor);
         my $totalstored = 0;          my $totalstored = 0;
           my $totalskippeduser = 0;
         my $now = time;          my $now = time;
         for (my $i=0;$i<=$#markers;$i++) {          for (my $i=0;$i<=$#markers;$i++) {
             my ($needsrelease,$needsnewer,$name,$namematch);              my ($needsrelease,$needsnewer,$name,$namematch);
Line 3135  sub assessparms { Line 3645  sub assessparms {
             }              }
             if ($markers[$i] =~ /\&(8|7|6|5)$/) {              if ($markers[$i] =~ /\&(8|7|6|5)$/) {
                 next if ($noeditgrp);                  next if ($noeditgrp);
               } elsif ($markers[$i] =~ /\&(4|3|2|1)$/) {
                   if ($uname eq '') {
                       $totalskippeduser ++;
                       next;
                   }
             }              }
             if ($markers[$i] =~ /\&(17|11|7|3)$/) {              if ($markers[$i] =~ /\&(17|11|7|3)$/) {
                 $namematch = 'maplevelrecurse';                  $namematch = 'maplevelrecurse';
Line 3273  sub assessparms { Line 3788  sub assessparms {
 # ---------------------------------------------------------------- Done storing  # ---------------------------------------------------------------- Done storing
         if ($totalstored) {          if ($totalstored) {
             $message.='<p class="LC_warning">'              $message.='<p class="LC_warning">'
                        .&mt('Changes for [quant,_1,parameter] saved.',$totalstored)
                        .'<br />'
                      .&mt('Changes can take up to 10 minutes before being active for all students.')                       .&mt('Changes can take up to 10 minutes before being active for all students.')
                      .&Apache::loncommon::help_open_topic('Caching')                       .&Apache::loncommon::help_open_topic('Caching')
                      .'</p>';                       .'</p>';
           } else {
               $message.='<p class="LC_info">'.&mt('No parameter changes saved.').'</p>';
           }
           if ($totalskippeduser) {
               $message .= '<p class="LC_warning">';
               if ($uhome eq 'no_host') {
                   $message .= &mt('Changes for [quant,_1,user-specific parameter] not saved because the username or ID was invalid.',
                                   $totalskippeduser);
               } elsif ($env{'form.userroles'} eq 'any') {
                   $message .= &mt('Changes for [quant,_1,user-specific parameter] not saved because the user does not have a course role.',
                                   $totalskippeduser);
               } else {
                   $message .= &mt('Changes for [quant,_1,user-specific parameter] not saved because the user is not a student.',
                                   $totalskippeduser);
               }
               $message .= '</p>';
         }          }
     }      }
   
Line 3298  sub assessparms { Line 3831  sub assessparms {
             'date_interval','int','float','string','string_lenient',              'date_interval','int','float','string','string_lenient',
             'string_examcode','string_deeplink','string_discussvote',              'string_examcode','string_deeplink','string_discussvote',
             'string_useslots','string_problemstatus','string_ip',              'string_useslots','string_problemstatus','string_ip',
             'string_questiontype') {              'string_questiontype','string_tex','string_grace') {
         $r->print('<input type="hidden" value="'.          $r->print('<input type="hidden" value="'.
             &HTML::Entities::encode($env{'form.recent_'.$item},'"&<>').              &HTML::Entities::encode($env{'form.recent_'.$item},'"&<>').
             '" name="recent_'.$item.'" />');              '" name="recent_'.$item.'" />');
Line 3306  sub assessparms { Line 3839  sub assessparms {
   
     # ----- Start Parameter Selection      # ----- 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(<<ENDPARMSELSCRIPT);      $r->print(<<ENDPARMSELSCRIPT);
 <script type="text/javascript">  <script type="text/javascript">
 // <![CDATA[  // <![CDATA[
 function parmsel_show() {  function parmsel_show() {
     document.getElementById('parmsel').style.display = "";      document.getElementById('parmsel').style.display = "";
     document.getElementById('parmsellink').style.display = "none";      document.getElementById('parmsellink').style.display = "none";
       $tablejs
 }  }
 // ]]>  // ]]>
 </script>  </script>
Line 3339  ENDPARMSELSCRIPT Line 3879  ENDPARMSELSCRIPT
         $r->print(&Apache::lonhtmlcommon::start_pick_box(undef,'parmlevel'));          $r->print(&Apache::lonhtmlcommon::start_pick_box(undef,'parmlevel'));
         &levelmenu($r,\%alllevs,$parmlev);          &levelmenu($r,\%alllevs,$parmlev);
         $r->print(&Apache::lonhtmlcommon::row_closure());          $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_closure());
         $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Parts to View')));          $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Parts to View')));
         &partmenu($r,\%allparts,\@psprt);          &partmenu($r,\%allparts,\@psprt);
Line 3419  ENDPARMSELSCRIPT Line 3959  ENDPARMSELSCRIPT
         if ($parm_permission->{'edit'}) {          if ($parm_permission->{'edit'}) {
             undef($readonly);               undef($readonly); 
         }          }
           $r->print('<div id="parmtable"'.$tabledivsty.'>');
   
         if ($parmlev eq 'full') {          if ($parmlev eq 'full') {
 #  #
Line 3635  ENDTABLEHEADFOUR Line 4176  ENDTABLEHEADFOUR
   
 #-------------------------------------------- for each map, gather information  #-------------------------------------------- for each map, gather information
             my $mapid;              my $mapid;
             foreach $mapid (sort {$maplist{$a} cmp $maplist{$b}} keys(%maplist)) {              foreach $mapid (sort { $a <=> $b } keys(%maplist)) {
                 my $maptitle = $maplist{$mapid};                  my $maptitle = $maplist{$mapid};
   
 #-----------------------  loop through ids and get all parameter types for map  #-----------------------  loop through ids and get all parameter types for map
Line 3852  ENDMAPONE Line 4393  ENDMAPONE
                      .'</center>'                       .'</center>'
             );              );
         } # end of $parmlev eq general          } # end of $parmlev eq general
           $r->print('</div>');
     }      }
     $r->print('</form>');      $r->print('</form>');
     if ($numreclinks) {      if ($numreclinks) {
Line 3958  sub readdata { Line 4500  sub readdata {
 # Stores parameter data, using form parameters directly.  # Stores parameter data, using form parameters directly.
 #  #
 # Uses the following form parameters. The variable part in the names is a resourcedata key (except for a modification for user data).  # Uses the following form parameters. The variable part in the names is a resourcedata key (except for a modification for user data).
 # set_* (except settext, setipallow, setipdeny, setdeeplink) - set a parameter value  # set_* (except settext, setipallow, setipdeny, setdeeplink, setgrace) - set a parameter value
 # del_* - remove a parameter  # del_* - remove a parameter
 # datepointer_* - set a date parameter (value is key_* refering to a set of other form parameters)  # datepointer_* - set a date parameter (value is key_* refering to a set of other form parameters)
 # dateinterval_* - set a date interval parameter (value refers to more form parameters)  # dateinterval_* - set a date interval parameter (value refers to more form parameters)
Line 3991  sub storedata { Line 4533  sub storedata {
             my $cmd=$1;              my $cmd=$1;
             my $thiskey=$2;              my $thiskey=$2;
             my ($altkey,$recursive,$tkey,$tkeyrec,$tkeynonrec);              my ($altkey,$recursive,$tkey,$tkeyrec,$tkeynonrec);
             next if ($cmd eq 'rec' || $cmd eq 'settext' || $cmd eq 'setipallow' || $cmd eq 'setipdeny' || $cmd eq 'setdeeplink');              next if ($cmd eq 'rec' || $cmd eq 'settext' || $cmd eq 'setipallow' || $cmd eq 'setipdeny' || $cmd eq 'setdeeplink' || $cmd eq 'setgrace');
             if ((($cmd eq 'set') || ($cmd eq 'datepointer') || ($cmd eq 'dateinterval') || ($cmd eq 'del')) &&               if ((($cmd eq 'set') || ($cmd eq 'datepointer') || ($cmd eq 'dateinterval') || ($cmd eq 'del')) && 
                  ($thiskey =~ /(?:sequence|page)\Q___(all)\E/)) {                   ($thiskey =~ /(?:sequence|page)\Q___(all)\E/)) {
                 unless ($thiskey =~ /(encrypturl|hiddenresource)$/) {                  unless ($thiskey =~ /(encrypturl|hiddenresource)$/) {
Line 4050  sub storedata { Line 4592  sub storedata {
                         if ($thiskey =~ /\.retrypartial$/) {                          if ($thiskey =~ /\.retrypartial$/) {
                             $name = 'retrypartial';                              $name = 'retrypartial';
                         }                          }
                       } elsif ($typeof eq 'string_tex') {
                           $name = 'texdisplay';
                     }                      }
                 } elsif ($cmd eq 'datepointer') {                  } elsif ($cmd eq 'datepointer') {
                     $data=&Apache::lonhtmlcommon::get_date_from_form($env{$key});                      $data=&Apache::lonhtmlcommon::get_date_from_form($env{$key});
Line 4389  sub parse_listdata_key { Line 4933  sub parse_listdata_key {
 # @param {string} $caller - name of the calling sub (overview|newoverview)  # @param {string} $caller - name of the calling sub (overview|newoverview)
 # @param {hash reference} $classlist - from loncoursedata::get_classlist  # @param {hash reference} $classlist - from loncoursedata::get_classlist
 # @param {boolean} $readonly - true if editing not allowed  # @param {boolean} $readonly - true if editing not allowed
   # @param {string} $parmlev - full|map
   # @param {hash reference} $hash_for_realm - keys: realm, values: numeric order  
   # @param {string} $pschp - selected map pc, or 'all'
 # @returns{integer} - number of $listdata parameters processed  # @returns{integer} - number of $listdata parameters processed
 sub listdata {  sub listdata {
     my ($r,$resourcedata,$listdata,$sortorder,$caller,$classlist,$readonly)=@_;      my ($r,$resourcedata,$listdata,$sortorder,$caller,$classlist,$readonly,$parmlev,$hash_for_realm,$pschp)=@_;
           
 # Start list output  # Start list output
   
Line 4417  sub listdata { Line 4964  sub listdata {
     foreach my $key (sort {      foreach my $key (sort {
         my ($astudent,$ares,$apart,$aparm) = &parse_listdata_key($a,$listdata);          my ($astudent,$ares,$apart,$aparm) = &parse_listdata_key($a,$listdata);
         my ($bstudent,$bres,$bpart,$bparm) = &parse_listdata_key($b,$listdata);          my ($bstudent,$bres,$bpart,$bparm) = &parse_listdata_key($b,$listdata);
           my ($aid,$bid);
           if ($caller eq 'newoverview') {
               if (ref($hash_for_realm) eq 'HASH') {
                   if (($parmlev eq 'map') && ($pschp eq 'all')) {
                       my ($aurl) = ($ares =~ /^(.+\.(?:sequence|page))___\(all\)$/);
                       my ($burl) = ($bres =~ /^(.+\.(?:sequence|page))___\(all\)$/);
                       $aid = $hash_for_realm->{$aurl};
                       $bid = $hash_for_realm->{$burl};
                   } elsif ($parmlev eq 'full') {
                       $aid = $hash_for_realm->{$ares};
                       $bid = $hash_for_realm->{$bres};
                   }
               }
           }
   
         # get the numerical order for the param          # get the numerical order for the param
         $aparm=$keyorder{'parameter_0_'.$aparm};          $aparm=$keyorder{'parameter_0_'.$aparm};
Line 4426  sub listdata { Line 4987  sub listdata {
   
         if ($sortorder eq 'realmstudent') {          if ($sortorder eq 'realmstudent') {
             if ($ares     ne $bres    ) {              if ($ares     ne $bres    ) {
                 $result = ($ares     cmp $bres);                  if ($caller eq 'newoverview') {
                       if (ref($hash_for_realm) eq 'HASH') {
                           if (($parmlev eq 'map') && ($pschp eq 'all')) {
                               $result = ($aid <=> $bid);
                           } elsif ($parmlev eq 'full') {
                               $result = ($aid <=> $bid);
                           } else {
                               $result = ($ares cmp $bres);
                           }
                       } else {
                           $result = ($ares cmp $bres);
                       }
                   } else {
                       $result = ($ares cmp $bres);
                   }
             } elsif ($astudent ne $bstudent) {              } elsif ($astudent ne $bstudent) {
                 $result = ($astudent cmp $bstudent);                  $result = ($astudent cmp $bstudent);
             } elsif ($apart    ne $bpart   ) {              } elsif ($apart    ne $bpart   ) {
Line 4436  sub listdata { Line 5011  sub listdata {
             if      ($astudent ne $bstudent) {              if      ($astudent ne $bstudent) {
                 $result = ($astudent cmp $bstudent);                  $result = ($astudent cmp $bstudent);
             } elsif ($ares     ne $bres    ) {              } elsif ($ares     ne $bres    ) {
                 $result = ($ares     cmp $bres);                  if ($caller eq 'newoverview') {
                       if (ref($hash_for_realm) eq 'HASH') {
                           if (($parmlev eq 'map') && ($pschp eq 'all')) {
                               $result = ($aid <=> $bid);
                           } elsif ($parmlev eq 'full') {
                               $result = ($aid <=> $bid);
                           } else {
                               $result = ($ares cmp $bres);
                           }
                       } else {
                           $result = ($ares cmp $bres);
                       }
                   } else {
                       $result = ($ares cmp $bres);
                   }
             } elsif ($apart    ne $bpart   ) {              } elsif ($apart    ne $bpart   ) {
                 $result = ($apart    cmp $bpart);                  $result = ($apart    cmp $bpart);
             }              }
Line 4465  sub listdata { Line 5054  sub listdata {
                 ($thiskey=~/^$env{'request.course.id'}\.(?:(.+)\.)*([\w\s\-]+)\.(\w+)$/);                  ($thiskey=~/^$env{'request.course.id'}\.(?:(.+)\.)*([\w\s\-]+)\.(\w+)$/);
             my $section=&mt('All Students');              my $section=&mt('All Students');
             $readonly = $readonlyall;              $readonly = $readonlyall;
               my $userscope;
             my $showval = $$resourcedata{$thiskey};               my $showval = $$resourcedata{$thiskey}; 
             if ($middle=~/^\[(.*)\]/) {              if ($middle=~/^\[(.*)\]/) {
                 my $issection=$1;                  my $issection=$1;
Line 4478  sub listdata { Line 5068  sub listdata {
                         }                          }
                     }                      }
                     $section=&mt('User').": ".&Apache::loncommon::plainname($stuname,$studom);                      $section=&mt('User').": ".&Apache::loncommon::plainname($stuname,$studom);
                       $userscope = 1;
                 } else {                  } else {
                     if (($env{'request.course.sec'} ne '') && ($caller eq 'overview')) {                      if (($env{'request.course.sec'} ne '') && ($caller eq 'overview')) {
                         if (exists($grouphash{$issection})) {                          if (exists($grouphash{$issection})) {
Line 4514  sub listdata { Line 5105  sub listdata {
             }              }
             if ($is_map) {              if ($is_map) {
                 my $leveltitle = &mt('Folder/Map');                  my $leveltitle = &mt('Folder/Map');
                   my $title = &Apache::lonnet::gettitle($mapurl);
                   if (ref($hash_for_realm) eq 'HASH') {
                       if ($hash_for_realm->{$mapurl} eq '1') {
                           $title = &mt('Main Content');
                       }
                   }
                 unless (($name eq 'hiddenresource') || ($name eq 'encrypturl')) {                     unless (($name eq 'hiddenresource') || ($name eq 'encrypturl')) {   
                     if ($caller eq 'newoverview') {                      if ($caller eq 'newoverview') {
                         my $altkey = $thiskey;                          my $altkey = $thiskey;
Line 4530  sub listdata { Line 5127  sub listdata {
                         $is_recursive = 1;                          $is_recursive = 1;
                     }                      }
                 }                  }
                 $realm='<span class="LC_parm_scope_folder">'.$leveltitle.': '.&Apache::lonnet::gettitle($mapurl).' <br /><span class="LC_parm_folder">('.$mapurl.')</span></span>';                  $realm='<span class="LC_parm_scope_folder">'.$leveltitle.': '.$title.' <br /><span class="LC_parm_folder">('.$mapurl.')</span></span>';
             } elsif ($middle) {              } elsif ($middle) {
                 my ($map,$id,$url)=&Apache::lonnet::decode_symb($middle);                  my ($map,$id,$url)=&Apache::lonnet::decode_symb($middle);
                   next if (($url =~ /\.(page|sequence)$/) && ($parmlev eq 'full') && ($caller eq 'newoverview'));
                 $realm='<span class="LC_parm_scope_resource">'.&mt('Resource').                  $realm='<span class="LC_parm_scope_resource">'.&mt('Resource').
                     ': '.&Apache::lonnet::gettitle($middle).                      ': '.&Apache::lonnet::gettitle($middle).
                     ' <br /><span class="LC_parm_symb">('.$url.' in '.$map.' id: '.                      ' <br /><span class="LC_parm_symb">('.$url.' in '.$map.' id: '.
Line 4570  sub listdata { Line 5168  sub listdata {
     # Ready to print      # Ready to print
     #      #
             my $parmitem = &standard_parameter_names($name);              my $parmitem = &standard_parameter_names($name);
               my $advice;
               if (($name eq 'mapalias') && ($middle) && (!$is_map)) {
                   if ($middle =~ m{^uploaded/}) {
                       $advice = &mt('Use Course Editor to set this.');
                   } else {
                       $advice = &mt('Use Resource Assembly Tool to set this.');
                   }
                   $advice = '<br /><span class="LC_fontsize_small LC_cusr_emph">'.$advice.'</span>';
               }
             $r->print(&tablestart($readonly,$is_map).              $r->print(&tablestart($readonly,$is_map).
                 &Apache::loncommon::start_data_table_row().                  &Apache::loncommon::start_data_table_row().
                 '<td><b>'.&mt($parmitem).                  '<td><b>'.&mt($parmitem).
                 '</b></td>');                  '</b>'.$advice.'</td>');
             unless ($readonly) {              unless ($readonly) {
                   my $disabled;
                   if (($name eq 'availablestudent') &&
                       (($showval eq '') || ($userscope))) {
                       $disabled = ' disabled="disabled"';
                   } elsif (($name eq 'mapalias') && ($showval eq '')) {
                       $disabled = ' disabled="disabled"';
                   }
                 $r->print('<td><input type="checkbox" name="del_'.                  $r->print('<td><input type="checkbox" name="del_'.
                         $thiskey.'" /></td>');                          $thiskey.'"'.$disabled.' /></td>');
             }              }
             $r->print('<td>');              $r->print('<td>');
             $foundkeys++;              $foundkeys++;
Line 4604  sub listdata { Line 5218  sub listdata {
                 $r->print(&date_interval_selector($thiskey,$name,                  $r->print(&date_interval_selector($thiskey,$name,
                           $showval,$readonly));                            $showval,$readonly));
             } elsif ($thistype =~ m/^string/) {              } elsif ($thistype =~ m/^string/) {
                   if ($name eq 'availablestudent') {
                       $readonly = 1;
                   } elsif (($name eq 'mapalias') && ($showval eq '')) {
                       $readonly = 1;
                   }
                 $r->print(&string_selector($thistype,$thiskey,                  $r->print(&string_selector($thistype,$thiskey,
                           $showval,$name,$readonly));                            $showval,$name,$readonly));
             } else {              } else {
Line 4646  sub listdata { Line 5265  sub listdata {
 sub get_date_interval_from_form {  sub get_date_interval_from_form {
     my ($key) = @_;      my ($key) = @_;
     my $seconds = 0;      my $seconds = 0;
       my $numnotnull = 0;
     foreach my $which (['days', 86400],      foreach my $which (['days', 86400],
                ['hours', 3600],                 ['hours', 3600],
                ['minutes', 60],                 ['minutes', 60],
                ['seconds',  1]) {                 ['seconds',  1]) {
         my ($name, $factor) = @{ $which };          my ($name, $factor) = @{ $which };
         if (defined($env{'form.'.$name.'_'.$key})) {          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$/) &&      if (($key =~ /\.interval$/) &&
Line 4671  sub get_date_interval_from_form { Line 5294  sub get_date_interval_from_form {
             $seconds .= '_'.$env{'form.done_'.$key.'_proctorkey'};              $seconds .= '_'.$env{'form.done_'.$key.'_proctorkey'};
         }          }
     }      }
       return if (!$numnotnull);
     return $seconds;      return $seconds;
 }  }
   
Line 4758  sub string_ip_selector { Line 5382  sub string_ip_selector {
   
 sub string_deeplink_selector {  sub string_deeplink_selector {
     my ($thiskey, $showval, $readonly) = @_;      my ($thiskey, $showval, $readonly) = @_;
     my (@components,%values,@current,%titles,%options,%optiontext,%defaults,%posslti);      my (@tables,%values,@current,%titles,%options,%optiontext,%defaults,
     @components = ('listing','scope','urls');          %selectnull,%domlti,%crslti,@possmenus,%components);
       @tables = ('upper','lower');
       %components = (
                       upper => ['state','others','listing','scope'],
                       lower => ['protect','menus','target','exit'],
                     );   
     %titles = &Apache::lonlocal::texthash (      %titles = &Apache::lonlocal::texthash (
                     state   => 'Access status',
                     others  => 'Hide other resources',
                   listing => 'In Contents and/or Gradebook',                    listing => 'In Contents and/or Gradebook',
                   scope   => 'Access scope for link',                    scope   => 'Access scope for link',
                   urls    => 'Supported link types',                    protect => 'Link protection',
                     menus   => 'Menu Items Displayed',
                     target  => 'Embedded?',
                     exit    => 'Exit Tool Button?',
               );                );
     %options = (      %options = (
                      state   => ['only','off','both'],
                      others  => ['hide','unhide'],
                    listing => ['full','absent','grades','details','datestatus'],                     listing => ['full','absent','grades','details','datestatus'],
                    scope   => ['res','map','rec'],                     scope   => ['res','map','rec'],
                    urls    => ['any','only','key','lti'],                     protect => ['none','key','ltid','ltic'],
                      menus   => ['std','colls'],
                      target  => ['_self','_top'],
                      exit    => ['no','yes','url'],
                );                 );
     %optiontext = &Apache::lonlocal::texthash (      %optiontext = &Apache::lonlocal::texthash (
                       only       => 'deep only',
                       off        => 'deeplink off',
                       both       => 'regular + deep',
                       hide       => 'Hidden',
                       unhide     => 'Unhidden',
                     full       => 'Listed (linked) in both',                      full       => 'Listed (linked) in both',
                     absent     => 'Not listed',                      absent     => 'Not listed',
                     grades     => 'Listed in grades only',                      grades     => 'Listed in grades only',
Line 4779  sub string_deeplink_selector { Line 5423  sub string_deeplink_selector {
                     res        => 'resource only',                      res        => 'resource only',
                     map        => 'enclosing map/folder',                      map        => 'enclosing map/folder',
                     rec        => 'recursive map/folder',                      rec        => 'recursive map/folder',
                     any        => 'regular + deep',                      none       => 'not in use',
                     only       => 'deep only',                      key        => 'key access',
                     key        => 'deep with key',                      ltic       => 'LTI access (course)',
                     lti        => 'deep with LTI launch',                      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',
                       ltid => 'Select Launcher', 
                       colls => 'Select',
                   );                    );
     if ($showval =~ /,/) {      if ($showval =~ /,/) {
           %values=();
         @current = split(/,/,$showval);          @current = split(/,/,$showval);
         ($values{'listing'}) = ($current[0] =~ /^(full|absent|grades|details|datestatus)$/);          ($values{'state'}) = ($current[0] =~ /^(only|off|both)$/);
         ($values{'scope'}) = ($current[1] =~ /^(res|map|rec)$/);          ($values{'others'}) = ($current[1] =~ /^(hide|unhide)$/);
         ($values{'urls'}) = ($current[2] =~ /^(any|only|key:\w+|lti:\d+)$/);          ($values{'listing'}) = ($current[2] =~ /^(full|absent|grades|details|datestatus)$/);
           ($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 {      } else {
           $defaults{'state'} = 'off',
           $defaults{'others'} = 'unhide',
         $defaults{'listing'} = 'full';          $defaults{'listing'} = 'full';
         $defaults{'scope'} = 'res';          $defaults{'scope'} = 'res';
         $defaults{'urls'} = 'any';          $defaults{'protect'} = 'none';
           $defaults{'menus'} = '0';
           $defaults{'target'} = '_top';
           $defaults{'exit'} = 'yes';
     }      }
     my $disabled;      my $disabled;
     if ($readonly) {      if ($readonly) {
         $disabled=' disabled="disabled"';          $disabled=' disabled="disabled"';
     }      }
     my %lti =       my %courselti =
         &Apache::lonnet::get_domain_lti($env{'course.'.$env{'request.course.id'}.'.domain'},          &Apache::lonnet::get_course_lti($env{'course.'.$env{'request.course.id'}.'.num'},
                                           $env{'course.'.$env{'request.course.id'}.'.domain'},
                                         'provider');                                          'provider');
       foreach my $item (keys(%courselti)) {
           if (ref($courselti{$item}) eq 'HASH') {
               $crslti{$item} = $courselti{$item}{'name'};
           }
       }
       my %lti =
           &Apache::lonnet::get_domain_lti($env{'course.'.$env{'request.course.id'}.'.domain'},
                                           'linkprot');
     foreach my $item (keys(%lti)) {      foreach my $item (keys(%lti)) {
         if (ref($lti{$item}) eq 'HASH') {          if (($item =~ /^\d+$/) && (ref($lti{$item}) eq 'HASH')) {
             unless ($lti{$item}{'requser'}) {              $domlti{$item} = $lti{$item}{'name'};
                 $posslti{$item} = $lti{$item}{'consumer'};          }
       }
       if ($env{'course.'.$env{'request.course.id'}.'.menucollections'}) {
           foreach my $item (split(/;/,$env{'course.'.$env{'request.course.id'}.'.menucollections'})) {
               my ($num,$value) = split(/\%/,$item);
               if ($num =~ /^\d+$/) {
                   push(@possmenus,$num);
             }              }
         }          }
     }      }
     my $output = '<input type="hidden" name="set_'.$thiskey.'" /><table><tr>';  
     foreach my $item ('listing','scope','urls') {      my $output = '<input type="hidden" name="set_'.$thiskey.'" />';
         $output .= '<th>'.$titles{$item}.'</th>';      foreach my $table ('upper','lower') {
     }          next unless (ref($components{$table}) eq 'ARRAY');
     $output .= '</tr><tr>';          $output .= '<table width="100%"><tr>';
     foreach my $item (@components) {          foreach my $item (@{$components{$table}}) {
         $output .= '<td>';              $output .= '<th>'.$titles{$item}.'</th>';
         if ($item eq 'urls') {          }
             my $selected = $values{$item};          $output .= '</tr><tr>';
             foreach my $option (@{$options{$item}}) {          foreach my $item (@{$components{$table}}) {
                 if ($option eq 'lti') {              $output .= '<td>';
                     next unless (keys(%posslti));              if (($item eq 'protect') || ($item eq 'menus') || ($item eq 'exit')) {
                 }                  my $selected = $values{$item};
                 my $checked;                  foreach my $option (@{$options{$item}}) {
                 if ($selected =~ /^\Q$option\E/) {                      if ($item eq 'protect') { 
                     $checked = ' checked="checked"';                          if ($option eq 'ltid') {
                 }                              next unless (keys(%domlti));
                 my $onclick;                          } elsif ($option eq 'ltic') {
                 unless ($readonly) {                              next unless (keys(%crslti));
                     my $esc_key = &js_escape($thiskey);                          }
                     $onclick = ' onclick="toggleDeepLink(this.form,'."'$item','$esc_key'".');"';                      } elsif (($item eq 'menus') && ($option eq 'colls')) {
                 }                          next unless (@possmenus);
                 $output .= '<span class="LC_nobreak"><label>'.                      }
                            '<input type="radio" name="deeplink_'.$item.'_'.$thiskey.'" value="'.$option.'"'.$onclick.$disabled.$checked.' />'."\n".                      my $checked;
                            $optiontext{$option}.'</label>';                      if ($item eq 'menus') {
                 if ($option eq 'key') {                          if (($selected =~ /^\d+$/) && (@possmenus) &&
                     my $visibility="hidden";                              (grep(/^\Q$selected\E$/,@possmenus))) {
                     my $currkey;                              if ($option eq 'colls') {
                     if ($checked) {                                  $checked = ' checked="checked"';
                         $visibility = "text";                              }
                         $currkey = (split(/\:/,$values{$item}))[1];                          } elsif (($option eq 'std') && ($selected == 0) && ($selected ne '')) {
                     }                              $checked = ' checked="checked"';
                     $output .= '&nbsp;'.                          }
                         '<input type="'.$visibility.'" name="deeplink_'.$option.'_'.$thiskey.'" id="deeplink_'.$option.'_'.$item.'_'.$thiskey.'" value="'.$currkey.'" size="6"'.$disabled.' />';                      } elsif ($selected =~ /^\Q$option\E/) {
                 } elsif ($option eq 'lti') {                          $checked = ' checked="checked"';
                     my $display="none";                      }
                     my ($currlti,$blankcheck);                      my $onclick;
                     if ($checked) {                      unless ($readonly) {
                         $display = 'inline-block';                          my $esc_key = &js_escape($thiskey);
                         $currlti = (split(/\:/,$values{$item}))[1];                          $onclick = ' onclick="toggleDeepLink(this.form,'."'$item','$esc_key'".');"';
                     } else {                      }
                         $blankcheck = ' selected="selected"';                      $output .= '<span class="LC_nobreak"><label>'.
                                  '<input type="radio" name="deeplink_'.$item.'_'.$thiskey.'" value="'.$option.'"'.$onclick.$disabled.$checked.' />'."\n".
                                  $optiontext{$option}.'</label>';
                       if (($item eq 'protect') && ($option eq 'key')) {
                           my $visibility="hidden";
                           my $currkey;
                           if ($checked) {
                               $visibility = "text";
                               $currkey = (split(/\:/,$values{$item}))[1];
                           }
                           $output .= '&nbsp;'.
                                      '<input type="'.$visibility.'" name="deeplink_'.$option.'_'.$thiskey.'" id="deeplink_'.$option.'_'.$item.'_'.$thiskey.'" value="'.$currkey.'" size="10"'.$disabled.' />';
                       } 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"';
                           }
                           if ($option eq 'ltid') {
                               @possibles = keys(%domlti);
                           } elsif ($option eq 'ltic') {
                               @possibles = keys(%crslti); 
                           } else {
                               @possibles = @possmenus;
                           }
                           $output .= '<div id="deeplinkdiv_'.$option.'_'.$item.'_'.$thiskey.'"'.
                                      ' style="display: '.$display.'">&nbsp;<select name="'.
                                      'deeplink_'.$option.'_'.$thiskey.'"'.$disabled.'>';
                           if (@possibles > 1) {
                               $output .= '<option value=""'.$blankcheck.'>'.$selectnull{$option}.
                                          '</option>'."\n";
                           }
                           foreach my $poss (sort { $a <=> $b } @possibles) {
                               my $selected;
                               if (($poss == $current) || (scalar(@possibles) ==1)) {
                                   $selected = ' selected="selected"';
                               }
                               my $shown = $poss;
                               if ($option eq 'ltid') {
                                   $shown = $domlti{$poss};
                               } elsif ($option eq 'ltic') {
                                   $shown = $crslti{$poss};
                               }
                               $output .= '<option value="'.$poss.'"'.$selected.'>'.$shown.'</option>';
                           }
                           $output .= '</select></div>';
                     }                      }
                     $output .= '<div id="deeplinkdiv_'.$option.'_'.$item.'_'.$thiskey.'"'.                      $output .= '</span> ';
                                ' style="display: '.$display.'">&nbsp;<select name="'.                  }
                                'deeplink_'.$option.'_'.$thiskey.'"'.$disabled.'>'.                  if ($item eq 'exit') {
                                '<option value=""'.$blankcheck.'>'.&mt('Select Provider').'</option>'."\n";                      my $exitsty = 'none';
                     foreach my $lti (sort { $a <=> $b } keys(%posslti)) {                      my $displayval;
                         my $selected;                      if ($values{$item} =~ /^(yes|url)/) { 
                         if ($lti == $currlti) {                          $exitsty = 'inline-block';
                             $selected = ' selected="selected"';                          my $currval = (split(/\:/,$values{$item}))[1];
                           if ($currval eq '') {
                               $displayval = 'Exit Tool';
                           } else {
                               $displayval = $currval;
                         }                          }
                         $output .= '<option value="'.$lti.'"'.$selected.'>'.$posslti{$lti}.'</option>';  
                     }                      }
                     $output .= '</select></div>';                      $output .= '<div id="deeplinkdiv_'.$item.'_'.$thiskey.'"'.
                                  ' style="display: '.$exitsty.'"><br />'.&mt('Button text').': '.
                                  '<input type="text" name="deeplink_exittext_'.$thiskey.'"'.
                                  ' id="deeplink_exittext_'.$thiskey.'" value="'.$displayval.'"'.
                                  ' size="10"'.$disabled.' /></div>';
                 }                  }
                 $output .= '</span> ';              } else {
             }                  my $selected = $values{$item};
                   my $defsel;
                   if ($selected eq '') {
                       $defsel = ' selected="selected"';
                   }
                   $output .= '<select name="deeplink_'.$item.'_'.$thiskey.'"'.$disabled.'>'."\n".
                              '<option value=""'.$defsel.'>'.&mt('Please select').'</option>'."\n";
                   foreach my $option (@{$options{$item}}) {
                       $output .= '<option value="'.$option.'"';
                       if ($option eq $selected) {
                           $output .= ' selected="selected"';
                       }
                       $output .= '>'.$optiontext{$option}.'</option>';
                   }
                   $output .= '</select>';
               }
               $output .= '</td>';
           }
           $output .= '</tr></table>'."\n";
           if ($table eq 'upper') {
               $output .= '<br />';
           }
       }
       return $output;
   }
   
   sub string_grace_selector {
       my ($thiskey, $showval, $readonly) = @_;
       my $addmore;
       unless ($readonly) {
           $addmore = "\n".'<button class="LC_add_grace_button">'.&mt('Add more').'</button>';
       }
       my $output = '<input type="hidden" name="set_'.$thiskey.'" value="" />'.
                    '<div class="LC_string_grace_wrap" id="LC_string_grace_'.$thiskey.'">'."\n".
                    '<div class="LC_string_grace_inner">'."\n";
       if ($showval ne '') {
           my @current;
           if ($showval =~ /,/) {
               @current = split(/,/,$showval);
         } else {          } else {
             my $selected = $values{$item};              @current = ($showval);
             my $defsel;          }
             if ($selected eq '') {          my $num = scalar(@current);
                 $defsel = ' selected="selected"';          foreach my $item (@current) {
             }              my ($delta,$fraction,$gradational) = split(/:/,$item);
             $output .= '<select name="deeplink_'.$item.'_'.$thiskey.'"'.$disabled.'>'."\n".              if (($delta =~ /^\d+$/) && ($fraction =~ /^(0|1)\.?\d*$/) && 
                        '<option value=""'.$defsel.'>'.&mt('Please select').'</option>'."\n";                  (($gradational eq 1) || ($gradational eq '0'))) {
             foreach my $option (@{$options{$item}}) {                  my $gradchk = '';
                 $output .= '<option value="'.$option.'"';                  if ($gradational) {
                 if ($option eq $selected) {                      $gradchk = ' checked="checked"';
                     $output .= ' selected="selected"';  
                 }                  }
                 $output .= '>'.$optiontext{$option}.'</option>';                  $output .= &grace_form($thiskey,$delta,$fraction,$gradchk,
                                          $readonly);
             }              }
             $output .= '</select>';  
         }          }
         $output .= '</td>';      } elsif (!$readonly) {
           $output .= &grace_form($thiskey,'','','',$readonly);
       }
       $output .= '</div>'.$addmore.'</div>';
       return $output;
   }
   
   sub grace_form {
       my ($thiskey,$delta,$fraction,$gradchkon,$readonly) = @_;
       my $disabled;
       if ($readonly) {
           $disabled = ' disabled="disabled"';
       }
       my %lt = &grace_titles();
       my $output = '<div><input type="hidden" name="setgrace_'.$thiskey.'" value="" />'.
                    '<fieldset class="LC_grace"><legend>'.$lt{'sinc'}.'</legend>';
       foreach my $which (['days', 86400, 31],
                          ['hours', 3600, 23],
                          ['minutes', 60, 59],
                          ['seconds',  1, 59]) {
           my ($name, $factor, $max) = @{ $which };
           my $amount;
           if ($delta ne '') {
               $amount = int($delta/$factor);
               $delta %= $factor;
           }
           my %select = ((map {$_ => $_} (0..$max)),
                         'select_form_order' => [0..$max]);
           $output .= &Apache::loncommon::select_form($amount,$name.'_'.$thiskey,
                                                      \%select,'',$readonly);
           $output .= '&nbsp;'.$lt{$name}.'&nbsp;&nbsp; ';
       }
       $output .= '</fieldset>'.
                  '<fieldset class="LC_grace"><legend>'.$lt{'pcr'}.'</legend>'.
                  '<input type="text" size="3" name="frac_'.$thiskey.'" value="'.$fraction.'"'.$disabled.' />'.
                  '&nbsp;&nbsp;<label><input type="checkbox" value="1" name="grad_'.$thiskey.'"'.$gradchkon.$disabled.' />'.
                  $lt{'grad'}.'</label></fieldset>';
       unless ($readonly) {
           $output .= '<a href="#" class="LC_remove_grace">'.$lt{'remo'}.'</a>';
     }      }
     $output .= '</tr></table>'."\n";      $output .= '</div>'."\n";
     return $output;      return $output;
 }  }
   
   sub grace_titles {
       return &Apache::lonlocal::texthash (
                                            sinc => 'Time past due',
                                            remo => 'Remove',
                                            pcr => 'Partial credit',
                                            grad => 'gradual',
                                            days => 'days',
                                            hours => 'hours',
                                            minutes => 'minutes',
                                            seconds => 'seconds',
       );
   }
   
 { # block using some constants related to parameter types (overview mode)  { # block using some constants related to parameter types (overview mode)
   
Line 4924  my %strings = Line 5752  my %strings =
              => [['_allowfrom_','Hostname(s), or IP(s) from which access is allowed'],               => [['_allowfrom_','Hostname(s), or IP(s) from which access is allowed'],
                  ['_denyfrom_','Hostname(s) or IP(s) from which access is disallowed']],                    ['_denyfrom_','Hostname(s) or IP(s) from which access is disallowed']], 
      'string_deeplink'       'string_deeplink'
              => [['on','Set choices for link protection, resource listing, and access scope']],               => [['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']],
        'string_grace'
                => [['on','Set grading scale and grace period for submissions after due date']],
     );      );
         
   
Line 4935  my %stringmatches = ( Line 5768  my %stringmatches = (
               => [['_allowfrom_','[^\!]+'],                => [['_allowfrom_','[^\!]+'],
                   ['_denyfrom_','\!']],                    ['_denyfrom_','\!']],
          'string_deeplink'           'string_deeplink'
               => [['on','^(full|absent|grades|details|datestatus)\,(res|map|rec)\,(any|only|key\:\w+|lti\:\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)(|:[^:;\'",]+)$']],
            'string_grace'
                 => [['on','^\d+,(0|1)\.?\d*,(0|1)']],
     );      );
   
 my %stringtypes = (  my %stringtypes = (
Line 4946  my %stringtypes = ( Line 5781  my %stringtypes = (
                     examcode     => 'string_examcode',                      examcode     => 'string_examcode',
                     acc          => 'string_ip',                      acc          => 'string_ip',
                     deeplink     => 'string_deeplink',                      deeplink     => 'string_deeplink',
                       grace        => 'string_grace',
                       texdisplay   => 'string_tex',
                   );                    );
   
 # Returns the possible values and titles for a given string type, or undef if there are none.  # Returns the possible values and titles for a given string type, or undef if there are none.
Line 5006  sub string_selector { Line 5843  sub string_selector {
             ($thistype eq 'string_discussvote') ||              ($thistype eq 'string_discussvote') ||
             ($thistype eq 'string_ip') ||              ($thistype eq 'string_ip') ||
             ($thistype eq 'string_deeplink') ||              ($thistype eq 'string_deeplink') ||
               ($thistype eq 'string_tex') ||
               ($thistype eq 'string_grace') ||
             ($name eq 'retrypartial')) {              ($name eq 'retrypartial')) {
         my ($got_chostname,$chostname,$cmajor,$cminor);           my ($got_chostname,$chostname,$cmajor,$cminor); 
         foreach my $possibilities (@{ $strings{$thistype} }) {          foreach my $possibilities (@{ $strings{$thistype} }) {
Line 5043  sub string_selector { Line 5882  sub string_selector {
     }      }
   
     if ($thistype eq 'string_ip') {      if ($thistype eq 'string_ip') {
         return &string_ip_selector($thiskey,$showval,$readonly);           return &string_ip_selector($thiskey,$showval,$readonly);
       } elsif ($thistype eq 'string_grace') {
           return &string_grace_selector($thiskey,$showval,$readonly);
     } elsif ($thistype eq 'string_deeplink') {      } elsif ($thistype eq 'string_deeplink') {
         return &string_deeplink_selector($thiskey,$showval,$readonly);          return &string_deeplink_selector($thiskey,$showval,$readonly);
     }      }
Line 5255  sub date_interval_selector { Line 6096  sub date_interval_selector {
         $showval  %= $factor;          $showval  %= $factor;
         my %select = ((map {$_ => $_} (0..$max)),          my %select = ((map {$_ => $_} (0..$max)),
                 'select_form_order' => [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,          $result .= &Apache::loncommon::select_form($amount,$name.'_'.$thiskey,
                             \%select,'',$readonly);                              \%select,'',$readonly);
         $result .= ' '.&mt($name);          $result .= ' '.&mt($name);
Line 5262  sub date_interval_selector { Line 6108  sub date_interval_selector {
     if ($name eq 'interval') {      if ($name eq 'interval') {
         unless ($skipval{'done'}) {          unless ($skipval{'done'}) {
             my $checkedon = '';              my $checkedon = '';
               my $checkedoff = '';
             my $checkedproc = '';              my $checkedproc = '';
             my $currproctorkey = '';              my $currproctorkey = '';
             my $currprocdisplay = 'hidden';              my $currprocdisplay = 'hidden';
             my $currdonetext = &mt('Done');              my $currdonetext = &mt('Done');
             my $checkedoff = ' checked="checked"';  
             if ($currval =~ /^(?:\d+)_done$/) {              if ($currval =~ /^(?:\d+)_done$/) {
                 $checkedon = ' checked="checked"';                  $checkedon = ' checked="checked"';
                 $checkedoff = '';  
             } elsif ($currval =~ /^(?:\d+)_done\:([^\:]+)\:$/) {              } elsif ($currval =~ /^(?:\d+)_done\:([^\:]+)\:$/) {
                 $currdonetext = $1;                  $currdonetext = $1;
                 $checkedon = ' checked="checked"';                  $checkedon = ' checked="checked"';
                 $checkedoff = '';  
             } elsif ($currval =~ /^(?:\d+)_done_proctor_(.+)$/) {              } elsif ($currval =~ /^(?:\d+)_done_proctor_(.+)$/) {
                 $currproctorkey = $1;                  $currproctorkey = $1;
                 $checkedproc = ' checked="checked"';                  $checkedproc = ' checked="checked"';
                 $checkedoff = '';  
                 $currprocdisplay = 'text';                  $currprocdisplay = 'text';
             } elsif ($currval =~ /^(?:\d+)_done\:([^\:]+)\:_proctor_(.+)$/) {              } elsif ($currval =~ /^(?:\d+)_done\:([^\:]+)\:_proctor_(.+)$/) {
                 $currdonetext = $1;                  $currdonetext = $1;
                 $currproctorkey = $2;                  $currproctorkey = $2;
                 $checkedproc = ' checked="checked"';                  $checkedproc = ' checked="checked"';
                 $checkedoff = '';  
                 $currprocdisplay = 'text';                  $currprocdisplay = 'text';
               } elsif ($currval ne '') {
                   $checkedoff = ' checked="checked"';
               } else {
                   $currdonetext = '';
             }              }
             my $onclick = ' onclick="toggleSecret(this.form,'."'done_','$thiskey'".');"';              my $onclick = ' onclick="toggleSecret(this.form,'."'done_','$thiskey'".');"';
             my $disabled;              my $disabled;
Line 5301  sub date_interval_selector { Line 6147  sub date_interval_selector {
                        '<input type="'.$currprocdisplay.'" id="done_'.$thiskey.'_proctorkey" '.                         '<input type="'.$currprocdisplay.'" id="done_'.$thiskey.'_proctorkey" '.
                        'name="done_'.$thiskey.'_proctorkey" value="'.&HTML::Entities::encode($currproctorkey,'"<>&').'"'.$disabled.' /></span><br />'.                         'name="done_'.$thiskey.'_proctorkey" value="'.&HTML::Entities::encode($currproctorkey,'"<>&').'"'.$disabled.' /></span><br />'.
                        '<span class="LC_nobreak">'.&mt('Button text').': '.                         '<span class="LC_nobreak">'.&mt('Button text').': '.
                        '<input type="text" name="done_'.$thiskey.'_buttontext" value="'.&HTML::Entities::encode($currdonetext,'"<>&').'"'.$disabled.' /></span>';                         '<input type="text" name="done_'.$thiskey.'_buttontext" id="done_'.$thiskey.'_buttontext" value="'.
                          &HTML::Entities::encode($currdonetext,'"<>&').'"'.$disabled.' /></span>';
         }          }
     }      }
     unless ($readonly) {      unless ($readonly) {
Line 5476  sub newoverview { Line 6323  sub newoverview {
             &toggleparmtextbox_js()."\n".              &toggleparmtextbox_js()."\n".
             &validateparms_js()."\n".              &validateparms_js()."\n".
             &ipacc_boxes_js()."\n".              &ipacc_boxes_js()."\n".
               &grace_js()."\n".
             &done_proctor_js()."\n".              &done_proctor_js()."\n".
             &deeplink_js()."\n".              &deeplink_js()."\n".
 '// ]]>  '// ]]>
Line 5542  ENDOVER Line 6390  ENDOVER
   
     &extractResourceInformation(\@ids, \%typep,\%keyp, \%allparms, \%allparts, \%allmaps,      &extractResourceInformation(\@ids, \%typep,\%keyp, \%allparms, \%allparts, \%allmaps,
                 \%mapp, \%symbp,\%maptitles,\%uris,                  \%mapp, \%symbp,\%maptitles,\%uris,
                 \%keyorder,\%defkeytype);                  \%keyorder,\%defkeytype,$pssymb);
   
     if (grep {$_ eq 'all'} (@psprt)) {      if (grep {$_ eq 'all'} (@psprt)) {
         @psprt = keys(%allparts);          @psprt = keys(%allparts);
Line 5554  ENDOVER Line 6402  ENDOVER
     $r->print('<div>');      $r->print('<div>');
     $r->print(&Apache::lonhtmlcommon::start_pick_box(undef,'parmlevel'));      $r->print(&Apache::lonhtmlcommon::start_pick_box(undef,'parmlevel'));
     &levelmenu($r,\%alllevs,$parmlev);      &levelmenu($r,\%alllevs,$parmlev);
     if ($parmlev ne 'general') {      $r->print(&Apache::lonhtmlcommon::row_closure());
         $r->print(&Apache::lonhtmlcommon::row_closure());      &mapmenu($r,\%allmaps,$pschp,\%maptitles,\%symbp,$parmlev);
         &mapmenu($r,\%allmaps,$pschp,\%maptitles,\%symbp);  
     }  
     $r->print(&Apache::lonhtmlcommon::row_closure(1));      $r->print(&Apache::lonhtmlcommon::row_closure(1));
     $r->print(&Apache::lonhtmlcommon::end_pick_box());      $r->print(&Apache::lonhtmlcommon::end_pick_box());
     $r->print('</div></div>');      $r->print('</div></div>');
Line 5595  ENDOVER Line 6441  ENDOVER
     $r->print('<div>');      $r->print('<div>');
     my $sortorder=$env{'form.sortorder'};      my $sortorder=$env{'form.sortorder'};
     unless ($sortorder) { $sortorder='realmstudent'; }      unless ($sortorder) { $sortorder='realmstudent'; }
     &sortmenu($r,$sortorder);      &sortmenu($r,$sortorder,'newoverview');
     $r->print('</div></div>');      $r->print('</div></div>');
   
     $r->print('<p><input type="submit" name="dis" value="'.&mt('Display').'" /></p>');      $r->print('<p><input type="submit" name="dis" value="'.&mt('Display').'" /></p>');
Line 5620  ENDOVER Line 6466  ENDOVER
   
 # List data  # List data
   
         &listdata($r,$resourcedata,$listdata,$sortorder,'newoverview',undef,$readonly);          my $hash_for_realm;
           if (($parmlev eq 'map') && (keys(%allmaps))) {
               %{$hash_for_realm} = reverse(%allmaps);
           } elsif (($parmlev eq 'full') && (keys(%symbp))) {
               for (my $i=0; $i<@ids; $i++) {
                   $hash_for_realm->{$symbp{$ids[$i]}} = $i;
               }
           }
           &listdata($r,$resourcedata,$listdata,$sortorder,'newoverview',undef,$readonly,$parmlev,$hash_for_realm,$pschp);
     }      }
     $r->print(&tableend());      $r->print(&tableend());
     unless ($readonly) {      unless ($readonly) {
Line 5698  sub overview { Line 6552  sub overview {
              &toggleparmtextbox_js()."\n".               &toggleparmtextbox_js()."\n".
              &validateparms_js()."\n".               &validateparms_js()."\n".
              &ipacc_boxes_js()."\n".               &ipacc_boxes_js()."\n".
                &grace_js()."\n".
              &done_proctor_js()."\n".               &done_proctor_js()."\n".
              &deeplink_js()."\n".               &deeplink_js()."\n".
              '// ]]>'."\n".               '// ]]>'."\n".
Line 5727  sub overview { Line 6582  sub overview {
   
     my $sortorder=$env{'form.sortorder'};      my $sortorder=$env{'form.sortorder'};
     unless ($sortorder) { $sortorder='realmstudent'; }      unless ($sortorder) { $sortorder='realmstudent'; }
     &sortmenu($r,$sortorder);      &sortmenu($r,$sortorder,'overview');
   
     my $submitbutton = '<input type="submit" value="'.&mt('Save').'" />';      my $submitbutton = '<input type="submit" value="'.&mt('Save').'" />';
   
Line 6987  sub parm_change_log { Line 7842  sub parm_change_log {
                     } else {                      } else {
                         if (&isdateparm($istype{$parmname})) {                          if (&isdateparm($istype{$parmname})) {
                             $showvalue = &Apache::lonlocal::locallocaltime($value);                              $showvalue = &Apache::lonlocal::locallocaltime($value);
                           } elsif (($istype{$parmname} eq 'string_grace') ||
                                    ($istype{$parmname} eq 'string_ip')) {
                               $showvalue =~ s/,/, /g;
                         }                          }
                     }                      }
                     $output .= $showvalue;                      $output .= $showvalue;

Removed from v.1.595  
changed lines
  Added in v.1.622


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>