[LON-CAPA-cvs] cvs: loncom /html/adm/helper parameter.helper resettimes.helper /interface loncommon.pm lonhelper.pm lonnavmaps.pm lonparmset.pm

raeburn raeburn at source.lon-capa.org
Thu Apr 23 12:56:44 EDT 2026


raeburn		Thu Apr 23 16:56:44 2026 EDT

  Modified files:              
    /loncom/interface	loncommon.pm lonhelper.pm lonnavmaps.pm 
                     	lonparmset.pm 
    /loncom/html/adm/helper	resettimes.helper parameter.helper 
  Log:
  - WCAG 2.2 compliance
    - Include labels for form elements.
    - Satisfy minimum spacing between touch targets.
    - Use <th> tags for column headings and row headings in data table
      with scope="row" attribute for latter.
    - For form elements in data table cells use aria-labelledby to reference 
      appropriate column and row headers.
    - Group form elements in fieldset with legend for screenreaders.
  
  
-------------- next part --------------
Index: loncom/interface/loncommon.pm
diff -u loncom/interface/loncommon.pm:1.1516 loncom/interface/loncommon.pm:1.1517
--- loncom/interface/loncommon.pm:1.1516	Tue Apr 21 07:30:27 2026
+++ loncom/interface/loncommon.pm	Thu Apr 23 16:56:43 2026
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # a pile of common routines
 #
-# $Id: loncommon.pm,v 1.1516 2026/04/21 07:30:27 raeburn Exp $
+# $Id: loncommon.pm,v 1.1517 2026/04/23 16:56:43 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -9624,7 +9624,7 @@
 
 table.LC_resourceList {
   font-size: 90%;
-  line-height: 170%;
+  line-height: 180%;
 }
 
 table.LC_resourceList tr.LC_odd_row th.LC_colheader {
@@ -9635,11 +9635,13 @@
 }
 
 table.LC_resourceList tr.LC_odd_row th,
+table.LC_paramDefault tr.LC_odd_row th.LC_rowheader,
 table#contentlist tr.LC_odd_row th {
   background-color: $data_table_light;
 }
 
 table.LC_resourceList tr.LC_even_row th,
+table.LC_paramDefault tr.LC_even_row th.LC_rowheader,
 table#contentlist tr.LC_even_row th {
   background-color: $data_table_dark;
 }
@@ -9649,6 +9651,8 @@
 }
 
 table.LC_resourceList tr th.LC_rowheader,
+table.LC_paramDefault tr.LC_odd_row th.LC_rowheader,
+table.LC_paramDefault tr.LC_even_row th.LC_rowheader,
 table#contentlist tr.LC_odd_row th.LC_rowheader,
 table#contentlist tr.LC_even_row th.LC_rowheader {
   font-weight: normal;
Index: loncom/interface/lonhelper.pm
diff -u loncom/interface/lonhelper.pm:1.208 loncom/interface/lonhelper.pm:1.209
--- loncom/interface/lonhelper.pm:1.208	Sun Apr 19 03:47:18 2026
+++ loncom/interface/lonhelper.pm	Thu Apr 23 16:56:43 2026
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # .helper XML handler to implement the LON-CAPA helper
 #
-# $Id: lonhelper.pm,v 1.208 2026/04/19 03:47:18 raeburn Exp $
+# $Id: lonhelper.pm,v 1.209 2026/04/23 16:56:43 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -641,9 +641,9 @@
     $buttons .= '</p>'; # '</fieldset>';
     }
 
-
-
-    $result .= '<h2 class="LC_heading_2">'.$stateTitle.$stateHelp.'</h2>';
+    if (($stateTitle ne '') || ($stateHelp ne '')) {
+        $result .= '<h2 class="LC_heading_2">'.$stateTitle.$stateHelp.'</h2>';
+    }
 
 #   $result .= '<div>';
 
@@ -2452,7 +2452,8 @@
 	    }
             $result .= '<th id="col'.$col.'" class="LC_colheader">'.&Apache::lonlocal::mt('Select').'</th>';
             if ($addparts) {
-                $result .= '<th class="LC_colheader">'.&Apache::lonlocal::mt('Select parts').'</th>';
+                $col ++;
+                $result .= '<th id="col'.$col.'" class="LC_colheader">'.&Apache::lonlocal::mt('Select parts').'</th>';
             }
             $result .= '<th class="LC_colheader">'.&Apache::lonlocal::mt('Name of Resource').'</th>';
             if ($addstatus) {
@@ -2557,12 +2558,14 @@
     };
     my $renderPartsFunc = sub {
         my ($resource, $part, $params) = @_;
+        my $colnum = 0;
 	my $col= "<td>";
 	my $id=$resource->{ID};
 	my $resource_name =   
 	    &HTML::Entities::encode(&$valueFunc($resource),"<>&\"'");
 	if ($addparts && (scalar(@{$resource->parts}) > 1)) {
-	    $col .= "<select onclick=\"javascript:updateRadio(this.form,'${var}_forminput','$resource_name');updateHidden(this.form,'$id','${var}');\" name='part_${id}_forminput'>\n";
+            $colnum ++;
+	    $col .= "<select onclick=\"javascript:updateRadio(this.form,'${var}_forminput','$resource_name');updateHidden(this.form,'$id','${var}');\" name='part_${id}_forminput' aria-labelledby='row".$params->{counter}." col".$colnum."'>\n";
 	    $col .= "<option value=\"$part\">".&Apache::lonlocal::mt('All Parts')."</option>\n";
 	    foreach my $part (@{$resource->parts}) {
 		$col .= "<option value=\"$part\">".&Apache::lonlocal::mt('Part: [_1]',$part)."</option>\n";
Index: loncom/interface/lonnavmaps.pm
diff -u loncom/interface/lonnavmaps.pm:1.588 loncom/interface/lonnavmaps.pm:1.589
--- loncom/interface/lonnavmaps.pm:1.588	Sun Apr 19 03:47:18 2026
+++ loncom/interface/lonnavmaps.pm	Thu Apr 23 16:56:43 2026
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # Navigate Maps Handler
 #
-# $Id: lonnavmaps.pm,v 1.588 2026/04/19 03:47:18 raeburn Exp $
+# $Id: lonnavmaps.pm,v 1.589 2026/04/23 16:56:43 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -1145,7 +1145,7 @@
     # We're done preparing and finally ready to start the rendering
     my $result;
     if (($params->{'caller'} eq 'printout') || ($params->{'caller'} eq 'newslot') ||
-        ($params->{'caller'} eq 'resettimes')) {
+        ($params->{'caller'} eq 'resettimes') || ($params->{'caller'} eq 'parameter')) {
         $result = '<th scope="row" id="row'.$params->{counter}.'" class="LC_middle LC_rowheader">';
     } else {
         $result = '<td class="LC_middle">';
@@ -1162,7 +1162,7 @@
 
     # Decide what to display
     $result .= "$newBranchText$linkopen$icon";
-    
+
     my $curMarkerBegin = '';
     my $curMarkerEnd = '';
 
@@ -1203,7 +1203,7 @@
     }
     $result .= "$curMarkerBegin$title$partLabel$curMarkerEnd$linkclose$editmapLink$nonLinkedText";
     if (($params->{'caller'} eq 'printout') || ($params->{'caller'} eq 'newslot') ||
-        ($params->{'caller'} eq 'resettimes')) {
+        ($params->{'caller'} eq 'resettimes') || ($params->{'caller'} eq 'parameter')) {
         $result .= "</th>";
     } else {
         $result .= "</td>";
@@ -1998,7 +1998,7 @@
         $args->{'counter'}++;
         unless ($tablestarted) {
             if (($args->{'caller'} eq 'printout') || ($args->{'caller'} eq 'newslot') ||
-                ($args->{'caller'} eq 'resettimes')) {
+                ($args->{'caller'} eq 'resettimes') || ($args->{'caller'} eq 'parameter')) {
                 $result .= &Apache::loncommon::start_data_table("LC_resourceList");
             } else {
                 $result .= &Apache::loncommon::start_data_table("LC_tableOfContent").
Index: loncom/interface/lonparmset.pm
diff -u loncom/interface/lonparmset.pm:1.633 loncom/interface/lonparmset.pm:1.634
--- loncom/interface/lonparmset.pm:1.633	Wed Dec 24 18:36:07 2025
+++ loncom/interface/lonparmset.pm	Thu Apr 23 16:56:43 2026
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # Handler to set parameters for assessments
 #
-# $Id: lonparmset.pm,v 1.633 2025/12/24 18:36:07 raeburn Exp $
+# $Id: lonparmset.pm,v 1.634 2026/04/23 16:56:43 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -7724,17 +7724,18 @@
     }
     $r->print(&mt('Manual setting rules apply to all interfaces.').'<br />'.
         &mt('Automatic setting rules apply to table mode interfaces only.'));
-    $r->print("\n".&Apache::loncommon::start_data_table().
+    $r->print("\n".&Apache::loncommon::start_data_table('LC_paramDefault').
           &Apache::loncommon::start_data_table_header_row().
-          "<th>".&mt('Rule for parameter').'</th><th>'.
-          &mt('Action').'</th><th>'.&mt('Value').'</th>'.
+          '<th id="rule-column">'.&mt('Rule for parameter').'</th><th id="action-column">'.
+          &mt('Action').'</th><th id="value-column">'.&mt('Value').'</th>'.
           &Apache::loncommon::end_data_table_header_row());
     foreach my $tempkey (&keysindisplayorder(\%allparms,\%keyorder)) {
         unless ($tempkey) { next; }
         $r->print("\n".&Apache::loncommon::start_data_table_row().
-            "<td>".$allparms{$tempkey}."\n<br />(".$tempkey.')</td><td>');
+            '<th scope="row" id="'.$tempkey.'-row" class="LC_rowheader">'
+           .$allparms{$tempkey}."\n<br />(".$tempkey.')</th>');
         my $action=&rulescache($tempkey.'_action');
-        $r->print('<select name="'.$tempkey.'_action">');
+        $r->print('<select name="'.$tempkey.'_action" aria-labelledby="rule-column '.$tempkey.'-row">');
         if (&isdateparm($defkeytype{$tempkey})) {
             for (my $i=0;$i<=$#dateoptions;$i++) {
             if ($dateoptions[$i]=~/\_$tempkey$/) { next; }
@@ -7752,8 +7753,8 @@
         }
         $r->print('</select>');
         unless (&isdateparm($defkeytype{$tempkey})) {
-            $r->print("\n<br />".&mt('Triggering value(s) of other parameter (optional, comma-separated):').
-                '<input type="text" size="20" name="'.$tempkey.'_triggervalue" value="'.&rulescache($tempkey.'_triggervalue').'" />');
+            $r->print("\n<br /><label>".&mt('Triggering value(s) of other parameter (optional, comma-separated):').
+                '<input type="text" size="20" name="'.$tempkey.'_triggervalue" value="'.&rulescache($tempkey.'_triggervalue').'" /></label>');
         }
         $r->print("\n</td><td>\n");
 
@@ -7762,24 +7763,30 @@
             my $hours=&rulescache($tempkey.'_hours');
             my $min=&rulescache($tempkey.'_min');
             my $sec=&rulescache($tempkey.'_sec');
+            my $legend = &mt('Value for: [_1]',$tempkey);
             $r->print(<<ENDINPUTDATE);
-    <input name="$tempkey\_days" type="text" size="4" value="$days" />$lt{'days'}<br />
-    <input name="$tempkey\_hours" type="text" size="4" value="$hours" />$lt{'hours'}<br />
-    <input name="$tempkey\_min" type="text" size="4" value="$min" />$lt{'min'}<br />
-    <input name="$tempkey\_sec" type="text" size="4" value="$sec" />$lt{'sec'}
+    <fieldset class="LC_borderless" style="line-height: 190%">
+    <legend class="LC_visually_hidden">$legend</legend>
+    <label><input name="$tempkey\_days" type="text" size="4" value="$days" />$lt{'days'}</label><br />
+    <label><input name="$tempkey\_hours" type="text" size="4" value="$hours" />$lt{'hours'}</label><br />
+    <label><input name="$tempkey\_min" type="text" size="4" value="$min" />$lt{'min'}</label><br />
+    <label><input name="$tempkey\_sec" type="text" size="4" value="$sec" />$lt{'sec'}</label>
+    </fieldset>
 ENDINPUTDATE
         } elsif ($defkeytype{$tempkey} eq 'string_yesno') {
                 my $yeschecked='';
                 my $nochecked='';
                 if (&rulescache($tempkey.'_value') eq 'yes') { $yeschecked=' checked="checked"'; }
                 if (&rulescache($tempkey.'_value') eq 'no') { $nochecked=' checked="checked"'; }
-
+            my $legend = &mt('Value for: [_1]',$tempkey);
             $r->print(<<ENDYESNO);
+    <fieldset class="LC_borderless" style="line-height: 190%"><legend class="LC_visually_hidden">$legend</legend>
     <label><input type="radio" name="$tempkey\_value" value="yes"$yeschecked /> $lt{'yes'}</label><br />
     <label><input type="radio" name="$tempkey\_value" value="no"$nochecked /> $lt{'no'}</label>
+    </fieldset>
 ENDYESNO
         } else {
-            $r->print('<input type="text" size="20" name="'.$tempkey.'_value" value="'.&rulescache($tempkey.'_value').'" />');
+            $r->print('<input type="text" size="20" name="'.$tempkey.'_value" value="'.&rulescache($tempkey.'_value').'" aria-labelledby="value-column '.$tempkey.'-row" />');
         }
         $r->print('</td>'.&Apache::loncommon::end_data_table_row());
     }
Index: loncom/html/adm/helper/resettimes.helper
diff -u loncom/html/adm/helper/resettimes.helper:1.12 loncom/html/adm/helper/resettimes.helper:1.13
--- loncom/html/adm/helper/resettimes.helper:1.12	Mon Dec  1 03:16:29 2025
+++ loncom/html/adm/helper/resettimes.helper	Thu Apr 23 16:56:44 2026
@@ -1,12 +1,21 @@
 <helper title="Reset Access Times" requiredpriv="mgr">
   <state name="START" title="Select Scope">
     <message>
-      Select
+      <span aria-hidden="true">Select</span>
+      <div>
+      <fieldset class="LC_borderless">
+      <legend class="LC_visually_hidden">
+      Select scope of access times reset
+      </legend>
     </message>
     <choices variable="harry">
       <choice computer='1' nextstate="Student">Reset times on one or more folders/maps, resources or the course for a single student.</choice>
       <choice computer='0' nextstate="Class">Reset times on a single folder/map, resource or the course for a section or the whole class.</choice>
       </choices>
+     <message>
+      </fieldset>
+      </div>
+     </message>
   </state>
   <state name="Student" title="Select Student">
     <message nextstate="SelectAccess">
@@ -15,9 +24,14 @@
     <student variable='stu1' coursepersonnel='true' activeonly='true' />
   </state>
 
-  <state name="SelectAccess">
+  <state name="SelectAccess" title="Select Accesses to Delete">
     <message nextstate="ConfirmStu">
-       This is a list of first access times and what was accessed, please select those you want deleted.
+      <span aria-hidden="true">This is a list of first access times and what was accessed, please select those you want deleted.</span>
+      <div>
+      <fieldset class="LC_borderless">
+      <legend class="LC_visually_hidden">
+      Select first access times to delete
+      </legend>
     </message>
     <choices variable='delete' multichoice='true'>
       <exec>
@@ -36,6 +50,10 @@
 	 }
       </exec>
     </choices>
+    <message>
+      </fieldset>
+      </div>
+    </message>
   </state>
 
   <state name="ConfirmStu">
Index: loncom/html/adm/helper/parameter.helper
diff -u loncom/html/adm/helper/parameter.helper:1.23 loncom/html/adm/helper/parameter.helper:1.24
--- loncom/html/adm/helper/parameter.helper:1.23	Sat Mar  5 21:49:52 2016
+++ loncom/html/adm/helper/parameter.helper	Thu Apr 23 16:56:44 2026
@@ -48,7 +48,12 @@
     </state>
 
   <state name="CHOOSE_LEVEL" title="Which Problem or Problems?">
-    <message>Which problems do you wish to set a parameter for?</message>
+    <message>
+      <span aria-hidden="true">Which problems do you wish to set a parameter for?</span>
+      <div>
+      <fieldset class="LC_borderless">
+      <legend class="LC_visually_hidden">Which problems do you wish to set a parameter for?</legend>
+    </message>
     <choices variable="GRANULARITY">
       <choice computer="whole_course" nextstate="CHOOSE_ACTION">
         Course default for all problems
@@ -67,6 +72,10 @@
         One particular problem (overrides folder and course defaults)
         </choice>
       </choices>
+     <message>
+      </fieldset>
+      </div>
+     </message>
     </state>
 
   <state name="CHOOSE_FOLDER" title="Select Folder">
@@ -90,10 +99,21 @@
     </state>
 
   <state name="CHOOSE_ACTION" title="Parameter Type">
-    <eval>return &mt('What parameter do you want to set for ' . 
+    <message><span aria-hidden="true"></message>
+    <eval>return &mt('What parameter do you want to set for ' .
       &{$helper->{DATA}->{'levelType'}}()
       . '?');
-      </eval>
+    </eval>
+    <message>
+      </span><div>
+      <fieldset class="LC_borderless">
+      <legend class="LC_visually_hidden">
+    </message>
+    <eval>return &mt('What parameter do you want to set for ' .
+      &{$helper->{DATA}->{'levelType'}}()
+      . '?');
+    </eval>
+    <message></legend></message>
     <choices variable="ACTION_TYPE">
       <nextstate>CHOOSE_DATE</nextstate>
       <choice computer="open_date" nextstate="CHOOSE_DATE">Set an <b>open date</b></choice>
@@ -102,10 +122,14 @@
       <choice computer="tries" nextstate="CHOOSE_TRIES">Set the <b>number of tries</b></choice>
       <choice computer="weight" nextstate="CHOOSE_WEIGHT">Set the <b>problem weight</b></choice>
       </choices>
+     <message>
+      </fieldset>
+      </div>
+     </message>
     </state>
 
   <state name="CHOOSE_WEIGHT" title="Set Problem Weight">
-    <eval>return &mt('What weight should be set for ' . 
+    <eval>return '<label>'.&mt('What weight should be set for ' . 
       &{$helper->{DATA}->{'levelType'}}()
       . '?').'<br />';
       </eval>
@@ -114,12 +138,15 @@
                    return &mt('[_1] is not an acceptable weight. Weight must be a positive number.','"'.$element->getValue().'"');
                  } 
                  return undef;
-        </validator>
-      </string>
-    </state>
+      </validator>
+    </string>
+    <message>
+      </label>
+    </message>
+  </state>
 
   <state name="CHOOSE_TRIES" title="Set Problem Tries">
-    <eval>return &mt('How many tries should be set for ' . 
+    <eval>return '<label>'.&mt('How many tries should be set for ' . 
       &{$helper->{DATA}->{'levelType'}}()
       . '?').'<br />';
       </eval>
@@ -127,9 +154,12 @@
       <validator>if ($val !~ /^[1234567890]+$/) { 
                    return &mt('[_1] is not an acceptable number of tries. Tries must be a positive number with no decimal point.','"'.$element->getValue().'"');} 
                  return undef;
-        </validator>
-      </string>
-    </state>
+      </validator>
+    </string>
+    <message>
+      </label>
+    </message>
+  </state>
 
   <state name="CHOOSE_DATE" title="Set Date">
     <eval>
@@ -137,19 +167,33 @@
        &{$helper->{DATA}->{'dateType'}}() . 
        ' be set to?').'<br /><br />';
       </eval>
-    <date variable="PARM_DATE" hoursminutes='1'>
+    <date variable="PARM_DATE" hoursminutes='1' aria-label="Date parameter">
       <nextstate>CHOOSE_STUDENT_LEVEL</nextstate>
       </date>
     </state>
 
   <state name="CHOOSE_STUDENT_LEVEL" title="Students Affected">
+    <message><span aria-hidden="true"></message>
     <eval>
-      return &mt('Set ' . 
+      return &mt('Set ' .
        &{$helper->{DATA}->{'dateType'}}() .
         ' for ' .
        &{$helper->{DATA}->{'levelType'}}() .
         ' for ...');
-      </eval>
+    </eval>
+    <message>
+      </span><div>
+      <fieldset class="LC_borderless">
+      <legend class="LC_visually_hidden">
+      </message>
+    <eval>
+      return &mt('Set ' .
+       &{$helper->{DATA}->{'dateType'}}() .
+        ' for ' .
+       &{$helper->{DATA}->{'levelType'}}() .
+        ' for ...');
+    </eval>
+    <message></legend></message>
     <choices variable="TARGETS">
       <condition>
         <clause>return 1 if ($env{'request.course.sec'} eq '')</clause>
@@ -165,8 +209,12 @@
       </condition>
       <choice computer="student" nextstate="CHOOSE_STUDENT">
          . . . for an individual <b>student</b> or <b>user</b></choice>
-      </choices>
-    </state>
+    </choices>
+    <message>
+      </fieldset>
+      </div>
+    </message>
+  </state>
 
   <state name="CHOOSE_SECTION" title="Select Section">
     <eval>


More information about the LON-CAPA-cvs mailing list