[LON-CAPA-cvs] cvs: loncom /homework optionresponse.pm /interface lonpdfupload.pm

raeburn raeburn at source.lon-capa.org
Tue Mar 17 11:56:55 EDT 2026


raeburn		Tue Mar 17 15:56:55 2026 EDT

  Modified files:              
    /loncom/interface	lonpdfupload.pm 
    /loncom/homework	optionresponse.pm 
  Log:
  - Bug 6121
    - Support checkbox mode for optionresponse in cases where (a) no form field 
      retrieved from unchecked boxes, and (b) where LON-CAPA problem needs value
      for checked boxes to be 'Off'.
  
  
-------------- next part --------------
Index: loncom/interface/lonpdfupload.pm
diff -u loncom/interface/lonpdfupload.pm:1.32 loncom/interface/lonpdfupload.pm:1.33
--- loncom/interface/lonpdfupload.pm:1.32	Sun Feb 22 23:27:03 2026
+++ loncom/interface/lonpdfupload.pm	Tue Mar 17 15:56:54 2026
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # PDF Form Upload Handler
 #
-# $Id: lonpdfupload.pm,v 1.32 2026/02/22 23:27:03 raeburn Exp $
+# $Id: lonpdfupload.pm,v 1.33 2026/03/17 15:56:54 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -284,7 +284,7 @@
 sub grade_pdf {
     my @pdfdata = @_;
     my ($result,$meta,%grades,%problems,%foreigncourse,%mismatchuser,
-        %types,%checkboxoff,$debug);
+        %types,%checkboxoff,%checkboxon,%checkboxtotal,%checkboxinfo,$debug);
 
     my $navmap = Apache::lonnavmaps::navmap->new();
     if (!defined($navmap)) {
@@ -354,8 +354,25 @@
             if ($type eq 'radiobuttonresponse' && $value eq 'Off' ) {
                 next;
             }
-            if (($type eq 'optionresponse') && ($HWVAL =~ /^HWHDN([^:]+):0$/)) {
-                $checkboxoff{$symb.$part}{'HWVAL'.$1} = $value;
+            if (($type eq 'optionresponse') && ($HWVAL =~ /^HWHDN(ON|OFF|NUM)([^:]+):0$/)) {
+                my ($key,$id) = ($1,$2);
+                if ($key eq 'ON') {
+                    $checkboxon{$symb.$part}{'HWVAL'.$id} = $value;
+                } elsif ($key eq 'OFF') {
+                    $checkboxoff{$symb.$part}{'HWVAL'.$id} = $value;
+                } else {
+                    $checkboxtotal{$symb.$part}{'HWVAL'.$id} = $value;
+                    unless (exists($checkboxinfo{$symb.$part})) {
+                        my $submit = $part;
+                        $submit =~ s/part_(.*)/submit_$1/;
+                        $checkboxinfo{$symb.$part} = {
+                                                        'resource' => $resource,
+                                                        'symb' => $symb,
+                                                        'submitted' => $part,
+                                                        $submit => 'Answer',
+                                                     };
+                    }
+                }
                 next;
             }
 
@@ -397,6 +414,45 @@
 
     $result .= '<h2 class="LC_heading_2">'.&mt('Result of PDF Form upload').'</h2>';
 
+    if (keys(%checkboxtotal)) {
+        foreach my $key (keys(%checkboxtotal)) {
+            if ((ref($checkboxtotal{$key}) eq 'HASH') && (ref($checkboxoff{$key}) eq 'HASH')) {
+                foreach my $hwvalprefix (keys(%{$checkboxtotal{$key}})) {
+                    if ($checkboxoff{$key}{$hwvalprefix} ne '') {
+                        my $unchecked = $checkboxoff{$key}{$hwvalprefix};
+                        my $total = $checkboxtotal{$key}{$hwvalprefix};
+                        my ($part, $type, $HWVAL, $input_id) = split(/&/,$key);
+                        if (($unchecked ne '') && ($total > 1)) {
+                            for (my $i=1; $i<$total; $i++) {
+                                my $hwval = $hwvalprefix.':'.$i;
+                                if ((!exists($types{$key})) ||
+                                    ((ref($types{$key}) eq 'HASH') && (!exists($types{$key}{$hwval})))) {
+                                    if (ref($problems{$key}) eq 'HASH') {
+                                        if ($problems{$key}{$hwval} eq '') {
+                                            $problems{$key}{$hwval} = $unchecked;
+                                        }
+                                    } else {
+                                        if (ref($checkboxinfo{$key}) eq 'HASH') {
+                                            $problems{$key} = $checkboxinfo{$key};
+                                        }
+                                        $problems{$key}{$hwval} = $unchecked;
+                                    }
+                                    if (!exists($types{$key})) {
+                                        $types{$key}{$hwval} = 'optionresponse';
+                                    } elsif (ref($types{$key}) eq 'HASH') {
+                                        if (!exists($types{$key}{$hwval})) {
+                                            $types{$key}{$hwval} = 'optionresponse';
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
     if (keys(%problems) > 0) {
         $result .= &Apache::loncommon::start_data_table()
                   .&Apache::loncommon::start_data_table_header_row()
@@ -422,12 +478,17 @@
                                 push(@{$problem{$hwval}},$ordered{$digit});
                             }
                         }
-                    } elsif (ref($checkboxoff{$key}) eq 'HASH') {
-                        if (($problem{$hwval} eq '') &&
-                            ($types{$key}{$hwval} eq 'optionresponse')) {
+                    } elsif ((ref($checkboxoff{$key}) eq 'HASH') && (ref($checkboxon{$key}) eq 'HASH')) {
+                        if ($types{$key}{$hwval} eq 'optionresponse') {
                             my ($hwvalprefix) = split(/:/,$hwval);
-                            if ($checkboxoff{$key}{$hwvalprefix} ne '') {
-                                $problem{$hwval} = $checkboxoff{$key}{$hwvalprefix};
+                            if (($problem{$hwval} eq '') || ($problem{$hwval} eq 'Off')) {
+                                if ($checkboxoff{$key}{$hwvalprefix} ne '') {
+                                    $problem{$hwval} = $checkboxoff{$key}{$hwvalprefix};
+                                }
+                            } elsif (($problem{$hwval} eq 'Yes') && ($checkboxon{$key}{$hwvalprefix} ne 'Yes')) {
+                                if ($checkboxon{$key}{$hwvalprefix} ne '') {
+                                    $problem{$hwval} = $checkboxon{$key}{$hwvalprefix};
+                                }
                             }
                         }
                     }
Index: loncom/homework/optionresponse.pm
diff -u loncom/homework/optionresponse.pm:1.207 loncom/homework/optionresponse.pm:1.208
--- loncom/homework/optionresponse.pm:1.207	Sun Feb 22 23:27:02 2026
+++ loncom/homework/optionresponse.pm	Tue Mar 17 15:56:55 2026
@@ -1,7 +1,7 @@
 # LearningOnline Network with CAPA
 # option list style responses
 #
-# $Id: optionresponse.pm,v 1.207 2026/02/22 23:27:02 raeburn Exp $
+# $Id: optionresponse.pm,v 1.208 2026/03/17 15:56:55 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -739,13 +739,13 @@
     my $checkboxopt;
     if ($target eq 'web') {
         $checkboxopt=&check_box_opt($target,$checkboxvalue, at opt);
-        if ($checkboxopt && (!$no_tfprompt)) {
+        if (($checkboxopt ne '') && (!$no_tfprompt)) {
             $result.='<br />'.
                     ($checkboxchoices?&mt('Choices: ').'<b>'.$opt[0].','.$opt[1].'</b>. ':'').
                      &mt('Select all that are [_1].','<b>'.$checkboxopt.'</b>');
         }
     }
-    my ($fieldname,$checkboxoff);
+    my ($fieldname,$checkboxoff,$hiddennum);
     if ($target eq 'tex' and $env{'form.pdfFormFields'} eq 'yes'
          && $Apache::inputtags::status[-1] eq 'CAN_ANSWER') {
         $fieldname = &Apache::lonenc::encrypted($env{'request.symb'},1);
@@ -761,16 +761,31 @@
         $escres =~ s{_}{\\_}g;
         $fieldname .= '\&part\_'.$escpart.'\&optionresponse';
         ($checkboxopt,$checkboxoff)=&check_box_opt($target,$checkboxvalue, at opt);
-
-# To support checkbox mode for optionresponse, include a hidden form
-# field in the PDF with the value set to the option in effect for
-# the unchecked checkboxes. When the submitted form data are processed
-# the values for any unchecked boxes (each null value in received form
-# data) are all set to the value retrieved from the hidden form field.
-
-        if ($checkboxopt) {
-            my $hidden = $fieldname.'\&HWHDN\_'.$escres.':';
-            $result .= &Apache::lonxml::print_pdf_hidden_textfield($hidden.'0',$checkboxoff).' ';
+#
+# To support checkbox mode for optionresponse, include three hidden form
+# fields in the PDF: (a) HWHDNOFF with its value set to option in effect for 
+# unchecked checkboxes, (b) HWHDNON with its value set to the option in 
+# effect for checked checkboxes, and (c) HWHDNNUM with number of checkboxes.
+#
+# When the submitted form data are processed, if the checked value is 'Off'
+# the value is reported as 'Yes', and this needs to be detected
+# and replaced with the required value, as retrieved from the value for
+# the HWHDNON form field.
+#
+# If the checked value is not 'Off', then the values of the unchecked boxes
+# may be reported as 'Off', and, if so, this needs to be detected and replaced 
+# with the required value retrieved from the value for the HWHDNOFF form field.
+#
+# If entries for the unchecked boxes are missing from the list of form fields
+# then form field items are created for each missing item with the value for
+# the the HWHDNOFF form field assigned to each item.
+#
+        if ($checkboxopt ne '') {
+            $hiddennum = $fieldname.'\&HWHDNNUM\_'.$escres.':';
+            my $hiddenoff = $fieldname.'\&HWHDNOFF\_'.$escres.':';
+            $result .= &Apache::lonxml::print_pdf_hidden_textfield($hiddenoff.'0',$checkboxoff).' ';
+            my $hiddenon = $fieldname.'\&HWHDNON\_'.$escres.':';
+            $result .= &Apache::lonxml::print_pdf_hidden_textfield($hiddenon.'0',$checkboxopt).' ';
             if (!$no_tfprompt) {
                 $result .= ($checkboxchoices?&mt('Choices: ').
                            '\textbf{'.$opt[0].','.$opt[1].'}. ':'').
@@ -795,7 +810,7 @@
 
       if($target eq 'tex' and $env{'form.pdfFormFields'} eq 'yes'
          && $Apache::inputtags::status[-1] eq 'CAN_ANSWER') {
-          if ($checkboxopt) {
+          if ($checkboxopt ne '') {
               $optionlist = '\vskip 4 mm'.
                             &Apache::lonxml::print_pdf_checkbox($fieldname.$temp,$checkboxopt);
           } else {
@@ -809,7 +824,7 @@
               if ($target eq 'tex' && $env{'form.pdfFormFields'} eq 'yes'
                   && $Apache::inputtags::status[-1] eq 'CAN_ANSWER'
                   && $Apache::lonhomework::type ne 'exam') {
-                  unless ($checkboxopt) {
+                  if ($checkboxopt eq '') {
                       $optionlist .= &Apache::lonxml::print_pdf_add_combobox_option($option);
                   }
               } else {
@@ -819,7 +834,7 @@
               if ($target eq 'tex' && $env{'form.pdfFormFields'} eq 'yes'
                   && $Apache::inputtags::status[-1] eq 'CAN_ANSWER'
                   && $Apache::lonhomework::type ne 'exam') {
-                  unless ($checkboxopt) {
+                  if ($checkboxopt eq '') {
                       $optionlist .= &Apache::lonxml::print_pdf_add_combobox_option($option);
                   }
               } else {
@@ -830,7 +845,7 @@
       if ($target ne 'tex') {
 	  if ($Apache::lonhomework::type ne 'exam') {
 # we are on the web, this is not an exam, and the problem can be answered
-              if ($checkboxopt) {
+              if ($checkboxopt ne '') {
 # generate checkboxes
                   my $fieldname=$Apache::inputtags::response['-1'].':'.$temp;
                   my $altopt=$opt[0];
@@ -931,7 +946,7 @@
               && $Apache::lonhomework::type ne 'exam') {
               $text =~ s/\\item//m;
               $result .= " $optionlist ";
-              if ($checkboxopt) {
+              if ($checkboxopt ne '') {
                   $result .= $text;
               } else {
                   $result .= &Apache::lonxml::print_pdf_end_combobox($text);
@@ -945,6 +960,13 @@
           $result.= '</div>';
       }
     }
+    if (($target eq 'tex') &&
+        ($env{'form.pdfFormFields'} eq 'yes') &&
+        ($Apache::inputtags::status[-1] eq 'CAN_ANSWER') &&
+        ($Apache::lonhomework::type ne 'exam') &&
+        ($checkboxopt ne '')) {
+        $result .= &Apache::lonxml::print_pdf_hidden_textfield($hiddennum.'0',$temp).' ';
+    }
   }
 
   if ($target eq 'web') {


More information about the LON-CAPA-cvs mailing list