[LON-CAPA-cvs] cvs: loncom /interface loncommon.pm loncourserespicker.pm londocs.pm lonsyllabus.pm

raeburn raeburn at source.lon-capa.org
Fri Dec 19 16:55:48 EST 2025


raeburn		Fri Dec 19 21:55:48 2025 EDT

  Modified files:              
    /loncom/interface	loncommon.pm loncourserespicker.pm londocs.pm 
                     	lonsyllabus.pm 
  Log:
  - WCAG 2 compliance
    - Headings descend sequentially
    - Replace use of <table> with <div> for layout
    - Include labels for form elements
  
  
-------------- next part --------------
Index: loncom/interface/loncommon.pm
diff -u loncom/interface/loncommon.pm:1.1489 loncom/interface/loncommon.pm:1.1490
--- loncom/interface/loncommon.pm:1.1489	Mon Dec 15 19:17:39 2025
+++ loncom/interface/loncommon.pm	Fri Dec 19 21:55:48 2025
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # a pile of common routines
 #
-# $Id: loncommon.pm,v 1.1489 2025/12/15 19:17:39 raeburn Exp $
+# $Id: loncommon.pm,v 1.1490 2025/12/19 21:55:48 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -2893,8 +2893,10 @@
 to be disabled, e.g., for the case where an instructor has a section-
 specific role, and is viewing/modifying parameters. An optional arg
 -- $id -- will be used as the id attribute of the select element. An
-optional arg -- $aria_labelledby -- will be included as the aria-labelledby
-attribute of the select element.
+optional arg -- $aria_labelledby -- will be included as the
+aria-labelledby attribute of the select element. An optional arg --
+$arialabel -- will be included as the aria-label attribute of the
+select element.
 
 See lonrights.pm for an example invocation and use.
 
@@ -2902,7 +2904,7 @@
 
 #-------------------------------------------
 sub select_form {
-    my ($def,$name,$hashref,$onchange,$readonly,$id,$aria_labelledby) = @_;
+    my ($def,$name,$hashref,$onchange,$readonly,$id,$aria_labelledby,$arialabel) = @_;
     return unless (ref($hashref) eq 'HASH');
     if ($onchange) {
         $onchange = ' onchange="'.$onchange.'"';
@@ -2914,10 +2916,13 @@
     if ($id ne '') {
         $id = ' id="'.$id.'"';
     }
+    my $label;
     if ($aria_labelledby ne '') {
-        $aria_labelledby = ' aria-labelledby="'.$aria_labelledby.'"';
+        $label = ' aria-labelledby="'.$aria_labelledby.'"';
+    } elsif ($arialabel ne '') {
+        $label = ' aria-label="'.$arialabel.'"';
     }
-    my $selectform = "<select name=\"$name\" size=\"1\"$onchange$disabled$id$aria_labelledby>\n";
+    my $selectform = "<select name=\"$name\" size=\"1\"$onchange$disabled$id$label>\n";
     my @keys;
     if (exists($hashref->{'select_form_order'})) {
 	@keys=@{$hashref->{'select_form_order'}};
Index: loncom/interface/loncourserespicker.pm
diff -u loncom/interface/loncourserespicker.pm:1.23 loncom/interface/loncourserespicker.pm:1.24
--- loncom/interface/loncourserespicker.pm:1.23	Mon Dec 15 03:33:08 2025
+++ loncom/interface/loncourserespicker.pm	Fri Dec 19 21:55:48 2025
@@ -1,6 +1,6 @@
 # The LearningOnline Network
 #
-# $Id: loncourserespicker.pm,v 1.23 2025/12/15 03:33:08 raeburn Exp $
+# $Id: loncourserespicker.pm,v 1.24 2025/12/19 21:55:48 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -405,7 +405,12 @@
                 '</fieldset>';
         }
         $display .= '</div>';
-    } elsif (($context eq 'examblock') || ($context eq 'shorturls') || ($context eq 'passback')) {
+    } elsif ($context eq 'shorturls') {
+        unless ($disabled) {
+            $display .= '<fieldset style="display: inline">'.
+                        '<legend>'.$togglebuttons.'</legend>'."\n";
+        }
+    } elsif (($context eq 'examblock') || ($context eq 'passback')) {
         $display .= $info.$togglebuttons;
     } elsif ($context eq 'dumpdocs') {
         $display .= $preamble.
@@ -492,6 +497,7 @@
                                 '<td> </td>'."\n";
                 }
             } elsif ($context ne 'passback') {
+                my $labeltext = ' aria-label="'.&mt('copy item').'"';
                 $display .= '<td><input type="checkbox" name="'.$chkname.'" value="'.$count.'" ';
                 if ($is_map) {
                     $display .= 'onclick="javascript:checkFolder(document.'.$formname.','."'$currelem'".')" ';
@@ -508,7 +514,7 @@
                         $display .= 'checked="checked"';
                     }
                 }
-                $display .= $disabled.' />'."\n";
+                $display .= $disabled.$labeltext.' />'."\n";
             }
             if ($context eq 'dumpdocs') {
                 $display .= '</td><td valign="top">';
@@ -638,7 +644,7 @@
                     }
                 }
                 $display .= '<td>'.$filepath.'</td>'.
-                            '<td><input type="text" size="40" name="namefor_'.$count.'" id="namefor_'.$count.'" value="'.$title.'" /></td>'."\n";
+                            '<td><input type="text" size="40" name="namefor_'.$count.'" id="namefor_'.$count.'" value="'.$title.'" aria-label="'.&mt('file saved as').'" /></td>'."\n";
             }
             $display .= &Apache::loncommon::end_data_table_row();
         }
@@ -646,14 +652,15 @@
     $display .= &Apache::loncommon::end_data_table();
     if ($context eq 'imsexport') {
         if ($numprobs > 0) {
-            $display .= '<p><span class="LC_nobreak">'.
-                        &mt('Export format for LON-CAPA problems:').
+            $display .= '<p><fieldset style="display: inline">'.
+                        '<legend>'.&mt('Export format for LON-CAPA problems').'</legend>'.
+                        '<span class="LC_nobreak">'.
                         '<label><input type="radio" name="format" value="xml" checked="checked" />'.
                         ' '.&mt('XML').'</label>'.(' ' x3).
                         '<label><input type="radio" name="format" value="html" />'.
                         ' '.&mt('HTML').'</label>'.(' ' x3).
                         '<label><input type="radio" name="format" value="plaintext" />'.
-                        ' '.&mt('Text').'</label></span></p>';
+                        ' '.&mt('Text').'</label></span></fieldset></p>';
         }
     }
     my $numcount;
@@ -684,7 +691,7 @@
             $display .=
                 '<p>'.
                 '<input type="submit" name="shorturls" value="'.
-                &mt('Create Tiny URL(s)').'" /></p>';
+                &mt('Create Tiny URL(s)').'" /></p></fieldset>';
         }
     } elsif ($context eq 'passback') {
         unless ($readonly) {
Index: loncom/interface/londocs.pm
diff -u loncom/interface/londocs.pm:1.732 loncom/interface/londocs.pm:1.733
--- loncom/interface/londocs.pm:1.732	Sat Dec 13 13:33:33 2025
+++ loncom/interface/londocs.pm	Fri Dec 19 21:55:48 2025
@@ -1,7 +1,7 @@
 # The LearningOnline Network
 # Documents
 #
-# $Id: londocs.pm,v 1.732 2025/12/13 13:33:33 raeburn Exp $
+# $Id: londocs.pm,v 1.733 2025/12/19 21:55:48 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -268,6 +268,7 @@
               &Apache::lonhtmlcommon::breadcrumbs('Copy uploaded content to Authoring Space')."\n");
     $r->print(&startContentScreen('tools'));
     my ($home,$other,%outhash)=&authorhosts();
+    $r->print('<h2 class="LC_heading_2">'.&mt('Copy uploaded content to Authoring').'</h2>');
     unless ($home) {
         $r->print('<p class="LC_info">'.&mt('No author or co-author roles on this server.').'</p>'); 
         $r->print(&endContentScreen());
@@ -644,7 +645,7 @@
     }
     $preamble .= '<div class="LC_left_float">'.
                  '<fieldset><legend>'.&mt('Folder in Authoring Space').'</legend>'.
-                 '<input type="text" size="30" name="authorfolder" value="'.$title.'" />'."\n".
+                 '<input type="text" size="30" name="authorfolder" value="'.$title.'" aria-label="'.&mt('Destination folder').'" />'."\n".
                  '</fieldset></div>'."\n";
     return $preamble;
 }
@@ -809,7 +810,7 @@
     my $resurl = "/res/$coursedom/$coursenum";
     my $res_exclude = &Apache::lonnet::res_exclude();
     if (($env{'form.authorspace'}) && ($env{'form.authorfolder'}=~/\w/)) {
-        $r->print('<h3>'.&mt('Copying Files and/or Sub-directories').'</h3>');
+        $r->print('<h2 class="LC_heading_2">'.&mt('Copying Files and/or Sub-directories').'</h2>');
         if ($readonly) {
             $r->print('<p class="LC_info">'.
                       &mt('You do not have permission to copy files and/or directories from Course Authoring Space.').
@@ -1266,6 +1267,7 @@
                              '  <input type="button" value="'.&mt('uncheck all').'"'.
                              ' onclick="javascript:uncheckAll(document.'.$formname.'.'.$chkname.')" />';
         }
+        $r->print('<h2 class="LC_heading_2">'.&mt('Copy from Course Authoring to User Authoring').'</h2>');
         my $preamble = &authorspace_selector($r,$formname,$home,$title,%outhash).
                        &courseresource_options($formname,$numpub).
                        '<div style="padding:0;clear:both;margin:0;border:0"></div>'."\n";
@@ -1413,10 +1415,11 @@
             } else {
                 $published = '<img src="'.$location.'/navmap.wrong.gif" alt="'.&mt('no').'" />';
             }
+            my $labeltext = ' aria-label="'.&mt('copy [_1]',&HTML::Entities::encode($item,'<>&"')).'"';
             $$displayref .= &Apache::loncommon::start_data_table_row().
                             '<td><input type="checkbox" name="'.$chkname.'" value="'.&escape($showpath.$item).'" '.
                             'onclick="javascript:checkResource(document.'.$formname.','."'$currelem'".')" '.
-                            $disabled.' /></td><td>';
+                            $disabled.$labeltext.' /></td><td>';
             for (my $i=0; $i<$currdepth; $i++) {
                 $$displayref .= "$whitespace\n";
             }
@@ -1457,17 +1460,17 @@
     $output .= '<div class="LC_left_float">'.
                '<fieldset><legend>'.&mt('Distribution to set in metadata').'</legend>'.
                &mt('Copyright').': '.
-               '<select name="copyright" onchange="showHideCustom(this,'."'LC_customfile'".');">'."\n".
+               '<select name="copyright" onchange="showHideCustom(this,'."'LC_customfile'".');" aria-label="'.&mt('copyright/distribution to set').'">'."\n".
                '<option value="default" selected="selected">'.$lt{'default'}.'</option>'."\n".
                '<option value="domain">'.$lt{'domain'}.'</option>'."\n".
                '<option value="public">'.$lt{'public'}.'</option>'."\n".
                '<option value="custom">'.$lt{'custom'}.'</option>'."\n".
                '</select><div id="LC_customfile" style="padding:0;clear:both;margin:0;border:0;display:none">'."\n".
-               '<input type="text" name="customrights" size="60" value="" />'.
+               '<input type="text" name="customrights" size="60" value="" aria-label="'.&mt('custom rights file to use').'"/>'.
                '<a href="javascript:openbrowser('."'$formname','customrights','rights'".');">'.
                $lt{'sel'}.'</a></div><br />'."\n".
                &mt('Source').' :'.
-               '<select name="sourceavail">'."\n".
+               '<select name="sourceavail" aria-label="'.&mt('availability of source XML').'">'."\n".
                '<option value="closed" selected="selected">'.$lt{'closed'}.'</option>'."\n".
                '<option value="open">'.$lt{'open'}.'</option>'."\n".
                '</select><br />'."\n".
@@ -4918,12 +4921,10 @@
             } else {
                 $noresmsg = &mt('Currently empty');
             }
-            $to_show .= &Apache::loncommon::start_scrollbox('400px','380px','200px','contentscroll')
-                       .'<div class="LC_info" id="contentlist">'
+            $to_show .= '<div class="LC_info" id="contentlist">'
                        .$noresmsg
                        .'<br /><br />'
-                       .'</div>'
-                       .&Apache::loncommon::end_scrollbox();
+                       .'</div>';
         }
     } else {
         if ($shown) {
@@ -6213,7 +6214,7 @@
                   '</div>');
         &Apache::lonnet::logthis('Symb list failed - could not create navmap object in '.lc($crstype).':'.$env{'request.course.id'});
     } else {
-        $r->print('<h4 class="LC_info">'.&mt("$crstype Content Identifiers").'</h4>'.
+        $r->print('<h2 class="LC_heading_2">'.&mt("$crstype Content Identifiers").'</h2>'.
                   &Apache::loncommon::start_data_table().
                   &Apache::loncommon::start_data_table_header_row().
                   '<th>'.&mt('Title').'</th><th>'.&mt('Identifier').'</th>'.
@@ -6253,7 +6254,7 @@
                   &endContentScreen());
         return '';
     } else {
-        $r->print('<h4 class="LC_info">'.&mt('Tiny URLs for deep-linking into course').'</h4>'."\n");
+        $r->print('<h2 class="LC_heading_2">'.&mt('Tiny URLs for deep-linking into course').'</h2>'."\n");
         $r->rflush();
         my $readonly;
         if ($canedit) {
@@ -6284,14 +6285,14 @@
     $r->print(&Apache::loncommon::start_page('Verify '.$crstype.' Content'));
     $r->print(&Apache::lonhtmlcommon::breadcrumbs('Verify '.$crstype.' Content'));
     $r->print(&startContentScreen('tools'));
-    $r->print('<h4 class="LC_info">'.&mt($crstype.' content verification').'</h4>');
-    $r->print('<form method="post" action="/adm/coursedocs"><p>'.
+    $r->print('<h2 class="LC_heading_2">'.&mt($crstype.' content verification').'</h2>');
+    $r->print('<form method="post" action="/adm/coursedocs"><div style="margin: 0;">'.
               &mt('Include a check if files copied from elsewhere are up to date (will increase verification time)?').
-              ' <span class="LC_nobreak">'.
-              '<label><input type="radio" name="checkstale" value="0" checked="checked" />'.
+              ' <fieldset class="LC_borderless"><legend class="LC_visually_hidden">'.&mt('Check for file updates').'</legend>'.
+              '<span class="LC_nobreak"><label><input type="radio" name="checkstale" value="0" checked="checked" />'.
               &mt('No').'</label>'.(' 'x2).
               '<label><input type="radio" name="checkstale" value="1" />'.
-              &mt('Yes').'</label></span></p><p>'.
+              &mt('Yes').'</label></span></fieldset></div><p>'.
               '<input type="submit" value="'.&mt('Verify Content').' "/>'.
               '<input type="hidden" value="1" name="tools" />'.
               '<input type="hidden" value="1" name="verify" /></p></form>');
@@ -6305,7 +6306,7 @@
     $r->print(&Apache::loncommon::start_page('Verify '.$crstype.' Content'));
     $r->print(&Apache::lonhtmlcommon::breadcrumbs('Verify '.$crstype.' Content'));
     $r->print(&startContentScreen('tools'));
-    $r->print('<h4 class="LC_info">'.&mt($crstype.' content verification').'</h4>'); 
+    $r->print('<h2 class="LC_heading_2">'.&mt($crstype.' content verification').'</h2>');
    $hashtied=0;
    undef %alreadyseen;
    %alreadyseen=();
@@ -6456,7 +6457,8 @@
 	       'lw' => 'Version changes since last Week',
 	       'sy' => 'Version changes since Yesterday',
                'al' => 'All Resources (possibly large output)',
-               'cd' => 'Change display', 
+               'cd' => 'Change display',
+               'cw' => 'Change window',
 	       'sd' => 'Display',
 	       'fi' => 'File',
 	       'md' => 'Modification Date',
@@ -6476,13 +6478,13 @@
         $readonly = 1;
     }
     $r->print(<<ENDHEADERS);
-<h4 class="LC_info">$header</h4>
+<h2 class="LC_heading_2">$header</h2>
 <form action="/adm/coursedocs" method="post">
 <input type="hidden" name="versions" value="1" />
 <div class="LC_left_float">
 <fieldset>
 <legend>$lt{'cd'}</legend>
-<select name="timerange">
+<select name="timerange" aria-label="$lt{'cw'}">
 <option value='all'$allsel>$lt{'al'}</option>
 <option value="-1"$startsel>$lt{'st'}</option>
 <option value="2592000"$monthsel>$lt{'lm'}</option>
@@ -6501,7 +6503,6 @@
 </div>
 <br clear="all" />
 <hr />
-<h4>$lt{'vers'}</h4>
 ENDHEADERS
     #number of columns for version history
     my %changedbytime;
@@ -6520,11 +6521,13 @@
     }
     if (keys(%changedbytime) == 0) {
         &untiehash();
+        $r->print('<h2 class="LC_heading_3">'.$lt{'vers'}.'</h2>');
         $r->print(&mt('No content changes in imported content in specified time frame').
                   &endContentScreen());
         return;
     }
     $r->print(
+       '<fieldset><legend>'.$lt{'vers'}.'</legend>'.
        '<input type="submit" name="setversions" value="'.$lt{'save'}.'"'.$disabled.' />'.
         &Apache::loncommon::start_data_table().
         &Apache::loncommon::start_data_table_header_row().
@@ -6543,9 +6546,10 @@
                 $currentversion='<span class="LC_error">'.&mt('Could not be determined.').'</span>';
             }
             my $linkurl=&Apache::lonnet::clutter($key);
+            my $title = &Apache::lonnet::gettitle($linkurl);
             $r->print(
                 &Apache::loncommon::start_data_table_row().
-                '<td><b>'.&Apache::lonnet::gettitle($linkurl).'</b><br />'.
+                '<td><b>'.$title.'</b><br />'.
                 '<a href="'.$linkurl.'" target="cat">'.$linkurl.'</a></td>'.
                 '<td align="right">'.$currentversion.'<span class="LC_fontsize_medium"><br />('.
                 &Apache::lonlocal::locallocaltime($chg).')</span></td>'.
@@ -6570,7 +6574,8 @@
                       {'select_form_order' => ['',1..$currentversion,'mostrecent'],
                       '' => '',
                       'mostrecent' => &mt('most recent'),
-                      map {$_,$_} (1..$currentversion)},'',$readonly));
+                      map {$_,$_} (1..$currentversion)},'',$readonly,'','',
+                      &mt('Use specific version for [_1]',$title)));
             my $lastold=1;
             for (my $prevvers=1;$prevvers<$currentversion;$prevvers++) {
                 my $url=$root.'.'.$prevvers.'.'.$extension;
@@ -6605,7 +6610,7 @@
     $r->print(
         &Apache::loncommon::end_data_table().
         '<input type="submit" name="setversions" value="'.$lt{'save'}.'"'.$disabled.' />'.
-        '</form>'
+        '</fieldset></form>'
     );
 
     &untiehash();
Index: loncom/interface/lonsyllabus.pm
diff -u loncom/interface/lonsyllabus.pm:1.157 loncom/interface/lonsyllabus.pm:1.158
--- loncom/interface/lonsyllabus.pm:1.157	Sun Mar 16 21:04:09 2025
+++ loncom/interface/lonsyllabus.pm	Fri Dec 19 21:55:48 2025
@@ -1,7 +1,7 @@
 # The LearningOnline Network
 # Syllabus
 #
-# $Id: lonsyllabus.pm,v 1.157 2025/03/16 21:04:09 raeburn Exp $
+# $Id: lonsyllabus.pm,v 1.158 2025/12/19 21:55:48 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -284,7 +284,7 @@
                     &print_header($r,$cnum,$cdom,$crstype,$allowed,$forceedit,
                                   \%syllabus,\%syllabusfields);
                     $r->print($output.
-                              &Apache::loncommon::end_page());
+                              '</div>'.&Apache::loncommon::end_page());
                 }
                 return OK;
             }
@@ -773,6 +773,7 @@
     if ($start_page) {
         $r->print($start_page);
     }
+    $r->print("\n".'<div class="LC_landmark" role="main" id="LC_main_content">'."\n");
 }
 
 sub get_breadcrumbs{
@@ -1005,37 +1006,26 @@
         my $rem = $i%($numinrow);
         if ($rem == 0) {
             if (($i > 0) && ($i < $numfields)) {
-                $table .= '</tr>';
+                $table .= '</div>';
             }
             if ($i < $numfields) {
-                $table .= '<tr>';
+                $table .= '<div role="row" class="LC_grid_row">';
             }
         }
-        if ($i == $numfields-1) {
-            my $rem = $numfields%($numinrow);
-            my $colsleft = $numinrow - $rem;
-            if ($colsleft > 1) {
-                $table .= '<td colspan="'.$colsleft.'">';
-            } else {
-                $table .= '</td>';
-            }
-        } else {
-            $table .= '<td>';
-        }
-        $table .=
-            '<label><input type="checkbox" name="showfield" value="'.$fieldnames[$i].'" '.
-            $checked.' id="showfield_'.$i.'" onclick="javascript:toggleBox('."'$fieldnames[$i]',this".');" />'.
-            $name.'</label></td>'."\n";
+        $table .= '<div role="gridcell" class="LC_grid_cell">'.
+                  '<label><input type="checkbox" name="showfield" value="'.$fieldnames[$i].'" '.
+                  $checked.' id="showfield_'.$i.'" onclick="javascript:toggleBox('."'$fieldnames[$i]',this".');" />'.
+                  $name.'</label></div>'."\n";
     }
     if ($table ne '') {
         my $rem = $numfields%($numinrow);
         my $colsleft = $numinrow - $rem;
-        if ($colsleft > 1 ) {
-            $table .= '<td colspan="'.$colsleft.'"> </td>';
-        } elsif ($colsleft == 1) {
-            $table .= '<td> </td>';
+        if ($colsleft) {
+            for (my $i=0; $i<$colsleft; $i++) {
+                $table .= '<div role="gridcell" class="LC_grid_cell"> </div>';
+            }
         }
-        $table = '<table>'.$table.'</tr></table>';
+        $table = '<div role="grid" class="LC_grid">'.$table.'</div></div>';
     }
     return $table;
 }


More information about the LON-CAPA-cvs mailing list