[LON-CAPA-cvs] cvs: loncom /publisher lonpublisher.pm

raeburn raeburn at source.lon-capa.org
Mon May 11 09:42:38 EDT 2026


raeburn		Mon May 11 13:42:38 2026 EDT

  Modified files:              
    /loncom/publisher	lonpublisher.pm 
  Log:
  - WCAG 2 compliance.
    - Include labels for form elements.
    - Group form elements in fieldset with legend for screenreaders.
    - Replace use of <table> for layout with <div>. 
  
  
-------------- next part --------------
Index: loncom/publisher/lonpublisher.pm
diff -u loncom/publisher/lonpublisher.pm:1.314 loncom/publisher/lonpublisher.pm:1.315
--- loncom/publisher/lonpublisher.pm:1.314	Mon Aug  4 19:21:52 2025
+++ loncom/publisher/lonpublisher.pm	Mon May 11 13:42:38 2026
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # Publication Handler
 #
-# $Id: lonpublisher.pm,v 1.314 2025/08/04 19:21:52 raeburn Exp $
+# $Id: lonpublisher.pm,v 1.315 2026/05/11 13:42:38 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -296,8 +296,8 @@
     $value=~s/\s+/ /gs;
     $title=&mt($title);
     $env{'form.'.$name}=$value;
-    return "\n".&Apache::lonhtmlcommon::row_title($title)
-           .'<input type="text" name="'.$name.'" size="80" value="'.$value.'" />'
+    return "\n".&Apache::lonhtmlcommon::row_title('<label for="'.$name.'">'.$title.'</label>')
+           .'<input type="text" name="'.$name.'" id="'.$name.'" size="80" value="'.$value.'" />'
            .&Apache::lonhtmlcommon::row_closure($noline);
 }
 
@@ -313,8 +313,8 @@
         $disabled = ' disabled="disabled"';
     }
     my $output =
-          "\n".&Apache::lonhtmlcommon::row_title($title)
-          .'<input type="text" name="'.$name.'" size="80" value="'.$value.'"'.$disabled.' />';
+          "\n".&Apache::lonhtmlcommon::row_title('<label for="'.$name.'">'.$title.'</label>')
+          .'<input type="text" name="'.$name.'" id="'.$name.'" size="80" value="'.$value.'"'.$disabled.' />';
     unless ($readonly) {
         $output .=
           '<br />'
@@ -350,8 +350,8 @@
     } else {
 	$env{'form.'.$name}=$idlist[0];
     }
-    my $selout="\n".&Apache::lonhtmlcommon::row_title($title)
-              .'<select name="'.$name.'">';
+    my $selout="\n".&Apache::lonhtmlcommon::row_title('<label for="'.$name.'">'.$title.'</label>')
+              .'<select name="'.$name.'" id="'.$name.'">';
     foreach my $id (@idlist) {
         $selout.='<option value="'.$id.'"';
         if ($id eq $value) {
@@ -367,10 +367,10 @@
 }
 
 sub select_level_form {
-    my ($value,$name)=@_;
+    my ($value,$name,$id)=@_;
     $env{'form.'.$name}=$value;
     if (!defined($value)) { $env{'form.'.$name}=0; }
-    return  &Apache::loncommon::select_level_form($value,$name);
+    return  &Apache::loncommon::select_level_form($value,$name,$id);
 }
 
 sub common_access {
@@ -395,7 +395,17 @@
                                             'closed'  => 'Closed - XML source is closed to everyone',
                                             'open'    => 'Open - XML source is open to people who want to use it',
                                             'sel'     => 'Select',
+                                            'chcd'    => 'Choose copyright/distribution',
+                                            'chsa'    => 'Choose source availability',
+                                            'enpa'    => 'Enter path of rights file or use Select',
+                                            'path'    => 'Path to published rights file',
                                         );
+    my $arialabel;
+    if ($name eq 'dist') {
+        $arialabel = 'aria-label="'.$lt{'chcd'}.'"';
+    } elsif ($name eq 'source') {
+        $arialabel = 'aria-label="'.$lt{'chsa'}.'"';
+    }
     my $output = <<"END";
 <span class="LC_nobreak">
 <label>
@@ -403,7 +413,7 @@
 onclick="showHideAccess(this,'$divid');" />
 $text</label></span>
 <div id="$divid" style="padding:0;clear:both;margin:0;border:0;display:none">
-<select name="$selname" id="$selid" $selonchange>
+<select name="$selname" id="$selid" $selonchange $arialabel>
 <option value="" selected="selected">$lt{'sel'}</option>
 END
     foreach my $val (@{$options}) {
@@ -414,7 +424,7 @@
     if ($name eq 'dist') {
         $output .= <<"END";
 <div id="$customdivid" style="padding:0;clear:both;margin:0;border:0;display:none">
-<input type="text" name="commoncustomrights" size="60" value="" />
+<input type="text" name="commoncustomrights" size="60" value="" placeholder="$lt{'enpa'}" aria-label="$lt{'path'}" />
 <a href="javascript:openbrowser('$formname','commoncustomrights','rights');">
 $lt{'sel'}</a></div>
 END
@@ -1319,6 +1329,7 @@
 # ------------------------------------------------------- Now have all metadata
 
     my %keywords=();
+    my ($hasautogen,$haskeywords);
         
     if (length($content)<500000) {
 	my $textonly=$content;
@@ -1336,10 +1347,9 @@
         foreach ($textonly=~m/[^\s]+/g) {  #match all but whitespaces
             unless ($nokeyref->{$_}) {
                 $keywords{$_}=1;
+                $hasautogen = 1;
             }
         }
-
-
     }
             
     foreach my $addkey (split(/[\"\'\,\;]/,$metadatafields{'keywords'})) {
@@ -1348,6 +1358,7 @@
 	$addkey=~s/\s$//;
 	if ($addkey=~/\w/) {
 	    $keywords{$addkey}=1;
+            $haskeywords = 1;
 	}
     }
 # --------------------------------------------------- Now we also have keywords
@@ -1396,54 +1407,65 @@
 }
 </script>
 END
+    my $legend;
+    if ($haskeywords) {
+        if ($hasautogen) {
+            $legend = &mt('Existing keywords and auto-generated suggestions');
+        } else {
+            $legend = &mt('Existing keywords');
+        }
+    } elsif ($hasautogen) {
+        $legend = &mt('Auto-generated keyword suggestions');
+    }
+    $env{'form.keywords'} = '';
     $keywordout.="\n".&Apache::lonhtmlcommon::row_title(&mt('Keywords'))
                 .$keywords_help
                 .'<input type="button" value="'.&mt('check all').'" onclick="javascript:checkAll(document.pubform.keywords)" />'
                 .'<input type="button" value="'.&mt('uncheck all').'" onclick="javascript:uncheckAll(document.pubform.keywords)" />'
-                .'</p><br />'
-                .&Apache::loncommon::start_data_table();
-    my $cols_per_row = 10;
-    my $colcount=0;
-    my $wordcount=0;
-    my $numkeywords = scalar(keys(%keywords));
-
-    foreach my $word (sort(keys(%keywords))) {
-        if ($colcount == 0) {
-            $keywordout .= &Apache::loncommon::start_data_table_row();
-        }
-        $colcount++;
-        $wordcount++;
-        if (($wordcount == $numkeywords) && ($colcount < $cols_per_row)) {
-            my $colspan = 1+$cols_per_row-$colcount;
-            $keywordout .= '<td colspan="'.$colspan.'">';
-        } else {
-            $keywordout .= '<td>';
-        }
-        $keywordout.='<label><input type="checkbox" name="keywords" value="'.$word.'"';
-        if ($metadatafields{'keywords'}) {
-            if ($metadatafields{'keywords'}=~/\Q$word\E/) {
+                .'</p><br />';
+    if ($haskeywords || $hasautogen) {
+        $keywordout.= '<fieldset class="LC_borderless">'
+                     .'<legend class="LC_visually_hidden">'.$legend.'</legend>'
+                     .'<div class="LC_grid" role="grid" style="margin: 0;">';
+        my $cols_per_row = 10;
+        my $colcount=0;
+        my $wordcount=0;
+        my $numkeywords = scalar(keys(%keywords));
+
+        foreach my $word (sort(keys(%keywords))) {
+            if ($colcount == 0) {
+                $keywordout .= '<div class="LC_grid_row" role="row">';
+            }
+            $colcount++;
+            $wordcount++;
+            $keywordout .= '<div class="LC_grid_cell" role="gridcell">'
+                          .'<label><input type="checkbox" name="keywords" value="'.$word.'"';
+            if ($metadatafields{'keywords'}) {
+                if ($metadatafields{'keywords'}=~/\Q$word\E/) {
+                    $keywordout.=' checked="checked"';
+                    $env{'form.keywords'}.=$word.',';
+                }
+            } elsif (&Apache::loncommon::keyword($word)) {
                 $keywordout.=' checked="checked"';
                 $env{'form.keywords'}.=$word.',';
             }
-        } elsif (&Apache::loncommon::keyword($word)) {
-            $keywordout.=' checked="checked"';
-            $env{'form.keywords'}.=$word.',';
+            $keywordout.=' />'.$word.'</label></div>';
+            if ($colcount == $cols_per_row) {
+                $keywordout.= '</div>';
+                $colcount=0;
+            }
         }
-        $keywordout.=' />'.$word.'</label></td>';
-        if ($colcount == $cols_per_row) {
-            $keywordout.=&Apache::loncommon::end_data_table_row();
-            $colcount=0;
+        if ($colcount > 0) {
+            $keywordout .= '</div>';
         }
-    }
-    if ($colcount > 0) {
-        $keywordout .= &Apache::loncommon::end_data_table_row();
-    }
 
-    $env{'form.keywords'}=~s/\,$//;
+        $env{'form.keywords'}=~s/\,$//;
 
-    $keywordout.=&Apache::loncommon::end_data_table_row()
-                 .&Apache::loncommon::end_data_table()
-                 .&Apache::lonhtmlcommon::row_closure();
+        $keywordout.= '</div></div>';
+    } else {
+        $keywordout.= &mt('No keywords auto-generated from resource content');
+    }
+    $keywordout.= &Apache::lonhtmlcommon::row_closure();
 
     $intr_scrout.=$keywordout;
 
@@ -1451,8 +1473,8 @@
 
     $intr_scrout.=&textfield('Notes','notes',$metadatafields{'notes'});
 
-    $intr_scrout.="\n".&Apache::lonhtmlcommon::row_title(&mt('Abstract'))
-                 .'<textarea cols="80" rows="5" name="abstract">'
+    $intr_scrout.="\n".&Apache::lonhtmlcommon::row_title('<label for="abstract">'.&mt('Abstract').'</label>')
+                 .'<textarea cols="80" rows="5" name="abstract" id="abstract">'
                  .$metadatafields{'abstract'}
                  .'</textarea>'
                  .&Apache::lonhtmlcommon::row_closure();
@@ -1460,12 +1482,12 @@
     $source=~/\.(\w+)$/;
 
     $intr_scrout.="\n".&Apache::lonhtmlcommon::row_title(&mt('Grade Levels'))
-                 .&mt('Lowest Grade Level:').' '
-                 .&select_level_form($metadatafields{'lowestgradelevel'},'lowestgradelevel')
+                 .'<label for="lowestgradelevel">'.&mt('Lowest Grade Level:').'</label> '
+                 .&select_level_form($metadatafields{'lowestgradelevel'},'lowestgradelevel','lowestgradelevel')
 #                .&Apache::lonhtmlcommon::row_closure();
 #   $intr_scrout.="\n".&Apache::lonhtmlcommon::row_title(&mt('Highest Grade Level'))
-                 .' '.&mt('Highest Grade Level:').' '
-                 .&select_level_form($metadatafields{'highestgradelevel'},'highestgradelevel')
+                 .' <label for="highestgradelevel">'.&mt('Highest Grade Level:').'</label> '
+                 .&select_level_form($metadatafields{'highestgradelevel'},'highestgradelevel','highestgradelevel')
                  .&Apache::lonhtmlcommon::row_closure();
 
     $intr_scrout.=&textfield('Standards','standards',$metadatafields{'standards'});
@@ -1549,8 +1571,8 @@
 #	$intr_scrout.=&text_with_browse_field('Source Custom Distribution File','sourcerights',$metadatafields{'sourcerights'},'rights');
 	my $uctitle=&mt('Obsolete');
         my $obsolete_checked=($metadatafields{'obsolete'})?' checked="checked"':'';
-        $intr_scrout.="\n".&Apache::lonhtmlcommon::row_title($uctitle)
-                     .'<input type="checkbox" name="obsolete"'.$obsolete_checked.' />'
+        $intr_scrout.="\n".&Apache::lonhtmlcommon::row_title('<label for="obsolete">'.$uctitle.'</label>')
+                     .'<input type="checkbox" name="obsolete" id="obsolete"'.$obsolete_checked.' />'
                      .&Apache::lonhtmlcommon::row_closure(1);
         $intr_scrout.=&text_with_browse_field('Suggested Replacement for Obsolete File',
 				    'obsoletereplacement',


More information about the LON-CAPA-cvs mailing list