--- loncom/homework/inputtags.pm 2011/03/07 22:38:09 1.285 +++ loncom/homework/inputtags.pm 2021/09/07 20:37:33 1.355 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # input definitons # -# $Id: inputtags.pm,v 1.285 2011/03/07 22:38:09 www Exp $ +# $Id: inputtags.pm,v 1.355 2021/09/07 20:37:33 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -60,7 +60,7 @@ use LONCAPA; BEGIN { - &Apache::lonxml::register('Apache::inputtags',('hiddenline','textfield','textline')); + &Apache::lonxml::register('Apache::inputtags',('hiddensubmission','hiddenline','textfield','textline')); } =pod @@ -125,6 +125,37 @@ sub initialize_inputtags { %Apache::inputtags::submission_display=(); } +# +# provides the onblur binding for spellchecking. This could be an +# empty string if spellchecking was not enabled. +# Jquery selector binding is done rather than setting an onblur +# attribute because we'll need to set the element's spellcheck language +# option dynamically so we need $(this) to be defined. +# +# @param id - The element id to bind. +# @param lang - Language in which spellchecking is desired. +# if undef, nothing is generated. +# @return string - onblur specification to do the requested spellchecking. +# +sub spellcheck_onblur { + my ($id, $lang) = @_; + my $result = ''; + if ($lang) { + + $result = < +\$('\#$id').blur(function() { + doSpellcheck('\#$id', '$lang'); + }); + + +JAVASCRIPT + + + } + return $result; +} + sub check_for_duplicate_ids { my %check; foreach my $id (@Apache::inputtags::partlist, @@ -185,7 +216,16 @@ sub start_textfield { } } unless ($newvariation) { - $oldresponse = &HTML::Entities::encode($Apache::lonhomework::history{"resource.$partid.$resid.submission"},'<>&"'); + if ((($env{'form.grade_username'} eq '') && ($env{'form.grade_domain'} eq '')) || + (($env{'form.grade_username'} eq $env{'user.name'}) && + ($env{'form.grade_domain'} eq $env{'user.domain'}))) { + $oldresponse = $Apache::lonhomework::history{"resource.$partid.$resid.submission"}; + } elsif (($Apache::lonhomework::history{"resource.$partid.type"} eq 'anonsurvey') || + ($Apache::lonhomework::history{"resource.$partid.type"} eq 'anonsurveycred')) { + $oldresponse = '* '.&mt('(only shown to submitter)').' *'; + } else { + $oldresponse = $Apache::lonhomework::history{"resource.$partid.$resid.submission"}; + } } if ($Apache::inputtags::status[-1] eq 'CAN_ANSWER') { my $cols = &Apache::lonxml::get_param('cols',$parstack,$safeeval); @@ -194,13 +234,20 @@ sub start_textfield { if ( $rows eq '') { $rows = 16; } my $addchars=&Apache::lonxml::get_param('addchars',$parstack,$safeeval); $result=''; + my $tagident = 'HWVAL_' . $resid; + my $itemid = 'HWVAL_'.$partid.'_'.$resid; if ($addchars) { - $result.=&addchars('HWVAL_'.$resid,$addchars); + $result.=&addchars($tagident, $addchars); } - my $textareaclass = 'class="LC_richDetectHtml"'; - $result.= '"; + my $partid=$Apache::inputtags::part; + my $resid = $Apache::inputtags::response[-1]; + my $itemid = 'HWVAL_' . $partid . '_' . $resid; + my $result = ""; + $result .= &spellcheck_onblur($itemid, $spellcheck); + return $result; } } elsif ($target eq 'edit') { $result=&Apache::edit::end_table(); @@ -330,6 +395,12 @@ sub start_textline { my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_; my $result = ""; my $input_id = &start_input($parstack,$safeeval); + + # The spellcheck attribute + # 1. enables spellchecking. + # 2. Provides the language code in which the spellchecking will be performed. + + my $spellcheck = &Apache::lonxml::get_param('spellcheck', $parstack, $safeeval); if ($target eq 'web') { $Apache::lonxml::evaluate--; my $partid=$Apache::inputtags::part; @@ -352,7 +423,18 @@ sub start_textline { } } unless ($newvariation) { - $oldresponse = $Apache::lonhomework::history{"resource.$partid.$id.submission"}; + if ((($env{'form.grade_username'} eq '') && ($env{'form.grade_domain'} eq '')) || + (($env{'form.grade_username'} eq $env{'user.name'}) && + ($env{'form.grade_domain'} eq $env{'user.domain'}))) { + $oldresponse = $Apache::lonhomework::history{"resource.$partid.$id.submission"}; + } elsif (($Apache::lonhomework::history{"resource.$partid.type"} eq 'anonsurvey') || + ($Apache::lonhomework::history{"resource.$partid.type"} eq 'anonsurveycred') || + ($Apache::lonhomework::type eq 'anonsurvey') || + ($Apache::lonhomework::type eq 'anonsurveycred')) { + $oldresponse = '* '.&mt('(only shown to submitter)').' *'; + } else { + $oldresponse = $Apache::lonhomework::history{"resource.$partid.$id.submission"}; + } &Apache::lonxml::debug("oldresponse $oldresponse is ".ref($oldresponse)); if (ref($oldresponse) eq 'ARRAY') { $oldresponse = $oldresponse->[$#Apache::inputtags::inputlist]; @@ -377,11 +459,25 @@ sub start_textline { $readonly=''; } my $name = 'HWVAL_'.$id; + my $itemid = 'HWVAL_'.$partid.'_'.$id; + # NOTE: the input id should match the one given by defaut_homework input_id(). + my $input_tag_id = $itemid.'_'.$input_id; if ($Apache::inputtags::status[-1] eq 'CANNOT_ANSWER') { $name = "none"; } - $result.= ''; + $result.= ''; + + $result .= &spellcheck_onblur($itemid, $spellcheck); + if (($Apache::inputtags::status['-1'] eq 'CAN_ANSWER') && + (($tagstack->[-2] eq 'formularesponse') || ($tagstack->[-2] eq 'mathresponse')) && + (&Apache::lonnet::EXT('resource.'.$partid.'_'.$id.'.turnoffeditor') ne 'yes')) { + $result.=&edit_mathresponse_button($input_tag_id); + } } if ($Apache::lonhomework::type eq 'exam' && &needs_exam_box($tagstack)) { @@ -400,12 +496,15 @@ sub start_textline { 'addchars',$token,10); $result.=&Apache::edit::select_arg('Readonly:','readonly', ['no','yes'],$token); + my $spell_langs = &spelling_languages(); + $result.=&Apache::edit::select_arg('Spellcheck for:', 'spellcheck', + $spell_langs, $token); $result.=&Apache::edit::end_row(); $result.=&Apache::edit::end_table(); } elsif ($target eq 'modified') { my $constructtag=&Apache::edit::get_new_args($token,$parstack, $safeeval,'size', - 'addchars','readonly'); + 'addchars','readonly', 'spellcheck'); if ($constructtag) { $result = &Apache::edit::rebuild_tag($token); } } elsif ($target eq 'tex' && $Apache::lonhomework::type ne 'exam') { @@ -478,6 +577,49 @@ sub end_hiddenline { return ""; } + +sub start_hiddensubmission { + my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_; + my $result = ""; + my $input_id = &start_input($parstack,$safeeval); + if ($target eq 'web') { + $Apache::lonxml::evaluate--; + if ($Apache::inputtags::status[-1] eq 'CAN_ANSWER') { + my $partid=$Apache::inputtags::part; + my $id=$Apache::inputtags::response[-1]; + if ($Apache::lonhomework::type ne 'exam') { + my $value = &Apache::lonxml::get_param('value',$parstack,$safeeval); + $value = &HTML::Entities::encode($value,'<>&"'); + $result= ''; + } + } + } elsif ($target eq 'edit') { + $result=&Apache::edit::tag_start($target,$token); + $result.=&Apache::edit::text_arg('Value:','value',$token,'15'); + $result.=&Apache::edit::end_row(); + $result.=&Apache::edit::end_table(); + } elsif ($target eq 'modified') { + my $constructtag=&Apache::edit::get_new_args($token,$parstack, + $safeeval,'value'); + if ($constructtag) { $result = &Apache::edit::rebuild_tag($token); } + } + + if ( ($target eq 'web' || $target eq 'tex') + && $Apache::lonhomework::type eq 'exam' + && &needs_exam_box($tagstack)) { + $result.=&exam_box($target); + } + return $result; +} + +sub end_hiddensubmission { + my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_; + if ($target eq 'web') { $Apache::lonxml::evaluate++; } + elsif ($target eq 'edit') { return ('','no'); } + &end_input(); + return ""; +} + =pod =item file_selector() @@ -505,7 +647,7 @@ sub file_selector { my $current_files_display = ¤t_file_submissions($part,$id); my $addfiles; if ($current_files_display) { - $result .= &Apache::lonhtmlcommon::row_title(&mt('Currently submitted files')). + $result .= &Apache::lonhtmlcommon::row_title(&mt('Files currently selected for submission')). $current_files_display. &Apache::lonhtmlcommon::row_closure(); $addfiles = &mt('Submit other file(s)'); @@ -519,26 +661,40 @@ sub file_selector { &mt('Allowed filetypes: [_1]',''.$uploadedfiletypes.'').'
'; } if ($maxfilesize) { - $constraints .= &mt('Combined size of all files not to exceed: [_1] MB[_2].', + $constraints .= &mt('Combined size of all files not to exceed: [_1] MB.', ''.$maxfilesize.'').'
'; } if ($constraints) { $result .= $constraints.'
'; } - if ($which eq 'uploadonly' || $which eq 'both') { - $result.=&mt('Submit a file: (only one file per submission)'). - '

'; + if ($which eq 'uploadonly' || $which eq 'both') { + my $free_space = $maxfilesize * 1048576; + $result .= &mt('Submit a file: (only one file per submission)'). + '
'. + '
'; } if ( $which eq 'both') { $result.='
'.''.&mt('OR:').'
'; } - if ($which eq 'portfolioonly' || $which eq 'both') { - $result.=$extratext.''. + if ($which eq 'portfolioonly' || $which eq 'both') { + my $symb = $env{'request.symb'}; + (undef,undef,my $res)=&Apache::lonnet::decode_symb($symb); + my $showsymb; + # If resource is a .task and URL is unencrypted, include symb in query string + # for url opened in portfolio file selection window. Can be used to override + # blocking of portfolio access resulting from an exam event in a different course. + if ($res =~ /\.task$/i) { + my $encsymb = &Apache::lonenc::check_encrypt($symb); + if ($symb eq $encsymb) { + $showsymb = $symb; + } + } + $result.=$extratext.''. &mt('Select Portfolio Files: (one or more files per submission)').'
'. ''. '
'; - } $result.=&Apache::lonhtmlcommon::row_closure(1); return $result; @@ -551,7 +707,17 @@ sub current_file_submissions { my $uploadedfile=$Apache::lonhomework::history{"resource.$part.$id.uploadedfile"}; my $portfiles=$Apache::lonhomework::history{"resource.$part.$id.portfiles"}; return if (($uploadedfile eq '') && ($portfiles !~/[^\s]/)); - my $header = &Apache::loncommon::start_data_table(). + my @unversioned; + foreach my $file (split(/\s*,\s*/,&unescape($portfiles))) { + my ($path,$name) = ($file =~ m{^(.*/)([^/]+)$}); + my ($origname,$version,$ext) = &Apache::lonnet::file_name_version_ext($name); + unless ($version) { + push(@unversioned,$file); + } + } + return if (!@unversioned); + my $header = &portpath_popup_js(). + &Apache::loncommon::start_data_table(). &Apache::loncommon::start_data_table_header_row(); if ($Apache::inputtags::status[-1] eq 'CAN_ANSWER') { $header .= ''.&mt('Delete?').''; @@ -560,7 +726,7 @@ sub current_file_submissions { ''.&mt('Size (MB)').''. ''.&mt('Last Modified').''. &Apache::loncommon::end_data_table_header_row(); - my (undef,$crsid,$udom,$uname)=&Apache::lonnet::whichuser(); + my ($symb,$crsid,$udom,$uname)=&Apache::lonnet::whichuser(); my ($cdom,$cnum) = ($crsid =~ /^($LONCAPA::match_domain)_($LONCAPA::match_courseid)$/); my ($result,$header_shown,%okfiles,%rows,%legacy,@bad_file_list); if ($uploadedfile) { @@ -579,9 +745,9 @@ sub current_file_submissions { push(@bad_file_list,$error); } } - if ($portfiles =~ /[^\s]/) { + if (@unversioned > 0) { my $prefix = "/uploaded/$udom/$uname/portfolio"; - foreach my $file (split(/\s*,\s*/,&unescape($portfiles))) { + foreach my $file (@unversioned) { my ($path,$name) = ($file =~ m{^(.*/)([^/]+)$}); my $url = $prefix.$path.$name; my $uploadedfile = &HTML::Entities::encode($url,'<>&"'); @@ -617,13 +783,24 @@ sub current_file_submissions { ' value="'.$portfile.'" id="HWFILE'.$jspart.'_'.$id.'_'.$num.'_delete" />'."\n"; $num ++; } - my $showname = $rows{$url}{path}.$name; + my $pathid = 'HWFILE'.$jspart.'_'.$id.'_'.$num.'_path'; + my $pathidtext = $pathid.'text'; + my ($showname,$showpath); if ($legacy{$url}) { $showname = $name.' '.&mt('not in portfolio'); + } else { + $showname = $name; + $showpath = '
'. + ''. + ''. + &mt('(Show path)').''. + '
'.$rows{$url}{path}.$name. +'
'; } $result .= ''.$showname.''."\n". + '" border="0" alt="" />'.$showname.''.$showpath.''."\n". ''.$rows{$url}{size}.''."\n". ''.$rows{$url}{lastmodified}.''."\n". &Apache::loncommon::end_data_table_row(); @@ -633,9 +810,11 @@ sub current_file_submissions { } } if ($header_shown) { - $result .= &Apache::loncommon::end_data_table(). - '
'. - &mt('Exclude existing file(s) from grading by checking the "Delete?" checkbox(es) and clicking "Submit Answer"').''; + $result .= &Apache::loncommon::end_data_table(); + if ($Apache::inputtags::status[-1] eq 'CAN_ANSWER') { + $result .= '
'. + &mt('Exclude existing file(s) from grading by checking the "Delete?" checkbox(es) and clicking "Submit Answer"').''; + } } if (@bad_file_list) { my $bad_files = ''. @@ -676,10 +855,47 @@ sub current_file_info { return ($status,\%info,$error); } +sub portpath_popup_js { + my %lt = &Apache::lonlocal::texthash( + show => '(Show path)', + hide => '(Hide)', + ); + return <<"END"; + + +END +} + sub valid_award { my ($award) =@_; foreach my $possibleaward ('EXTRA_ANSWER','MISSING_ANSWER', 'ERROR', - 'NO_RESPONSE', + 'NO_RESPONSE','WRONG_NUMBOXESCHECKED', 'TOO_LONG', 'UNIT_INVALID_INSTRUCTOR', 'UNIT_INVALID_STUDENT', 'UNIT_IRRECONCIBLE', 'UNIT_FAIL', 'NO_UNIT', @@ -699,7 +915,7 @@ sub valid_award { { my @awards = ('EXTRA_ANSWER', 'MISSING_ANSWER', 'ERROR', 'NO_RESPONSE', - 'TOO_LONG', + 'WRONG_NUMBOXESCHECKED','TOO_LONG', 'UNIT_INVALID_INSTRUCTOR', 'UNIT_INVALID_STUDENT', 'UNIT_IRRECONCIBLE', 'UNIT_FAIL', 'NO_UNIT', 'UNIT_NOTNEEDED', 'WANTED_NUMERIC', 'BAD_FORMULA', 'NOT_FUNCTION', @@ -789,6 +1005,23 @@ sub finalizeawards { $j++; } + # if at least one response item is set to include lenient grading + # and that item is partially correct then overall award reflects + # that, unless an award for one of the other response items does + # not fall within the basic awards for correct or incorrect. + if ($Apache::inputtags::leniency) { + if (($$awardref[$which] eq 'INCORRECT') + && (grep { $_ eq 'EXACT_ANS' || + $_ eq 'APPROX_ANS' || + $_ eq 'ASSIGNED_SCORE' } (@$awardref)) + && !((grep { $_ ne 'INCORRECT' && + $_ ne 'EXACT_ANS' && + $_ ne 'APPROX_ANS' && + $_ ne 'ASSIGNED_SCORE' } (@$awardref)))) { + return ('ASSIGNED_SCORE'); + } + } + if (defined($which)) { if (ref($nameref)) { return ($$awardref[$which],$$msgref[$which],$$nameref[$which]); @@ -801,7 +1034,7 @@ sub finalizeawards { } sub decideoutput { - my ($award,$awarded,$awardmsg,$solved,$previous,$target,$nocorrect)=@_; + my ($award,$awarded,$awardmsg,$solved,$previous,$target,$nocorrect,$tdclass)=@_; my $message=''; my $button=0; @@ -814,6 +1047,7 @@ sub decideoutput { 'not_charged_try' => 'LC_answer_not_charged_try', 'no_grade' => 'LC_answer_no_grade', 'no_message' => 'LC_no_message', + 'no_charge_warn' => 'LC_answer_warning', ); my $part = $Apache::inputtags::part; @@ -827,7 +1061,7 @@ sub decideoutput { # my $computer = ($handgrade || $nocorrect)? '' - : " ".&mt("Computer's answer now shown above."); + : &mt("Computer's answer now shown above."); &Apache::lonxml::debug("handgrade has :$handgrade:"); if ($previous) { $previousmsg=&mt('You have entered that answer before'); } @@ -842,8 +1076,8 @@ sub decideoutput { $message=&mt('Incorrect.'); $css_class=$possible_class{'charged_try'}; } - if ($env{'request.filename'} =~ - m|/res/lib/templates/examupload.problem$|) { + if ($handgrade || + ($env{'request.filename'}=~/\/res\/lib\/templates\/(examupload|DropBox).problem$/)) { $message = &mt("A score has been assigned."); $added_computer_text=1; } else { @@ -851,7 +1085,9 @@ sub decideoutput { $message = '\textbf{'.$message.'}'; } else { $message = "".$message.""; - $message.= $computer; + if ($computer) { + $message = "$computer $message"; + } } $added_computer_text=1; if ($awarded > 0) { @@ -868,7 +1104,13 @@ sub decideoutput { } } } - if ($awarded==1) { $button=0; } else { $button=1; } + if ($awarded >= 1) { + $button=0; + } elsif (&Apache::lonnet::EXT("resource.$part.retrypartial") !~/^1|on|yes$/i) { + $button=0; + } else { + $button=1; + } $previousmsg=''; } elsif ($solved =~ /^excused/) { if ($target eq 'tex') { @@ -889,7 +1131,9 @@ sub decideoutput { $message = '\textbf{'.&mt('You are correct.').'}'; } else { $message = "".&mt('You are correct.').""; - $message.= $computer; + if ($computer) { + $message = "$computer $message"; + } } $added_computer_text=1; if ($awarded > 0 @@ -918,8 +1162,19 @@ sub decideoutput { if ($target ne 'tex') { $message .= &Apache::loncommon::help_open_topic('Some_Items_Were_Not_Submitted'); } - $css_class=$possible_class{'not_charged_try'}; + if (&Apache::lonhomework::show_some_problem_status()) { + $css_class=$possible_class{'no_charge_warn'}; + } else { + $css_class=$possible_class{'not_charged_try'}; + } $button = 1; + } elsif ($award eq 'WRONG_NUMBOXESCHECKED') { + $message = &mt('Number of boxes checked outside permissible range (either too few or too many).'); + if ($target ne 'tex') { + $message .= &Apache::loncommon::help_open_topic('Wrong_Num_Boxes_Checked'); + } + $css_class=$possible_class{'not_charged_try'}; + $button = 1; } elsif ($award eq 'ERROR') { $message = &mt('An error occurred while grading your answer.'); $css_class=$possible_class{'not_charged_try'}; @@ -940,7 +1195,7 @@ sub decideoutput { $css_class=$possible_class{'not_charged_try'}; $button=1; } elsif ($award eq 'EXCESS_FILESIZE') { - $message = &mt('Submission won\'t be graded. The combined size of submitted files exceeded the amount allowed.'); + $message = &mt("Submission won't be graded. The combined size of submitted files exceeded the amount allowed."); $css_class=$possible_class{'not_charged_try'}; $button=1; } elsif ($award eq 'FILENAME_INUSE') { @@ -950,7 +1205,7 @@ sub decideoutput { } else { $message .= '
'; } - $message .= &mt('Please use a different file name.'); + $message .= &mt('Please use a different filename.'); $css_class=$possible_class{'not_charged_try'}; $button=1; } elsif ($award eq 'INVALID_FILETYPE') { @@ -960,8 +1215,12 @@ sub decideoutput { } elsif ($award eq 'SIG_FAIL') { my ($used,$min,$max)=split(':',$awardmsg); my $word = ($used < $min) ? 'more' : 'fewer'; - $message = &mt("Submission not graded. Use $word digits.",$used); - $css_class=$possible_class{'not_charged_try'}; + $message = &mt("Submission not graded. Use $word significant figures."); + if (&Apache::lonhomework::show_some_problem_status()) { + $css_class=$possible_class{'no_charge_warn'}; + } else { + $css_class=$possible_class{'not_charged_try'}; + } $button=1; } elsif ($award eq 'UNIT_INVALID_INSTRUCTOR') { $message = &mt('Error in instructor specifed unit. This error has been reported to the instructor.', $awardmsg); @@ -971,21 +1230,37 @@ sub decideoutput { } elsif ($award eq 'UNIT_INVALID_STUDENT') { $message = &mt('Unable to interpret units. Computer reads units as "[_1]".',&markup_unit($awardmsg,$target)); if ($target ne 'tex') {$message.=&Apache::loncommon::help_open_topic('Physical_Units');} - $css_class=$possible_class{'not_charged_try'}; + if (&Apache::lonhomework::show_some_problem_status()) { + $css_class=$possible_class{'no_charge_warn'}; + } else { + $css_class=$possible_class{'not_charged_try'}; + } $button=1; } elsif ($award eq 'UNIT_FAIL' || $award eq 'UNIT_IRRECONCIBLE') { $message = &mt('Incompatible units. No conversion found between "[_1]" and the required units.',&markup_unit($awardmsg,$target)); if ($target ne 'tex') {$message.=&Apache::loncommon::help_open_topic('Physical_Units');} - $css_class=$possible_class{'not_charged_try'}; + if (&Apache::lonhomework::show_some_problem_status()) { + $css_class=$possible_class{'no_charge_warn'}; + } else { + $css_class=$possible_class{'not_charged_try'}; + } $button=1; } elsif ($award eq 'UNIT_NOTNEEDED') { $message = &mt('Only a number required. Computer reads units of "[_1]".',&markup_unit($awardmsg,$target)); - $css_class=$possible_class{'not_charged_try'}; + if (&Apache::lonhomework::show_some_problem_status()) { + $css_class=$possible_class{'no_charge_warn'}; + } else { + $css_class=$possible_class{'not_charged_try'}; + } $button=1; } elsif ($award eq 'NO_UNIT') { $message = &mt("Units required").'.'; if ($target ne 'tex') {$message.=&Apache::loncommon::help_open_topic('Physical_Units')}; - $css_class=$possible_class{'not_charged_try'}; + if (&Apache::lonhomework::show_some_problem_status()) { + $css_class=$possible_class{'no_charge_warn'}; + } else { + $css_class=$possible_class{'not_charged_try'}; + } $button=1; } elsif ($award eq 'COMMA_FAIL') { $message = &mt("Proper comma separation is required").'.'; @@ -1027,6 +1302,7 @@ sub decideoutput { } elsif ($award eq 'ANONYMOUS_CREDIT') { $message = &mt("Your anonymous submission has been recorded, and credit awarded."); $css_class=$possible_class{'correct'}; + $button=1; } elsif ($award eq 'DRAFT') { $message = &mt("Copy saved but not submitted."); $css_class=$possible_class{'not_charged_try'}; @@ -1077,13 +1353,33 @@ sub decideoutput { if (&Apache::lonhomework::hide_problem_status() && $Apache::inputtags::status[-1] ne 'SHOW_ANSWER' && &hide_award($award)) { - $message = &mt("Answer Submitted: Your final submission will be graded after the due date."); + $message = &mt("Answer Submitted: Your final submission will be graded after the due date."); + my @interval= &Apache::lonnet::EXT("resource.$part.interval"); + if ($interval[0] =~ /\d+/) { + my $first_access=&Apache::lonnet::get_first_access($interval[1]); + if (defined($first_access)) { + my $due_date= &Apache::lonnet::EXT("resource.$part.duedate"); + my ($timelimit) = ($interval[0] =~ /^(\d+)/); + unless (($due_date) && ($due_date < $first_access + $timelimit)) { + $message = &mt("Answer Submitted: Your final submission will be graded when the time limit is reached."); + } + } + } $css_class=$possible_class{'no_grade'}; $button=1; + if ($env{'course.'.$env{'request.course.id'}.'.type'} eq 'Placement') { + if ($Apache::inputtags::status[-1] eq 'CANNOT_ANSWER') { + $message = 'Answer Submitted'; + } else { + undef($message); + } + } } if ($Apache::inputtags::status[-1] eq 'SHOW_ANSWER' && !$added_computer_text && $target ne 'tex') { - $message.= $computer; + if ($computer) { + $message = "$computer $message"; + } $added_computer_text=1; } if ($Apache::lonhomework::type eq 'practice') { @@ -1277,14 +1573,11 @@ sub setgradedata { if ($award eq 'SUBMITTED') { &Apache::response::add_to_gradingqueue(); } - if (($Apache::lonhomework::type eq 'anonsurvey') || - ($Apache::lonhomework::type eq 'anonsurveycred') || - ($Apache::lonhomework::type eq 'randomizetry')) { - $Apache::lonhomework::results{"resource.$id.type"} = $Apache::lonhomework::type; - } - if ($Apache::lonhomework::type eq 'randomizetry') { - $Apache::lonhomework::results{"resource.$id.rndseed"} = $env{'form.'.$id.'.rndseed'}; - } + $Apache::lonhomework::results{"resource.$id.type"} = $Apache::lonhomework::type; + $Apache::lonhomework::results{"resource.$id.duedate"} = &Apache::lonnet::EXT("resource.$id.duedate"); + $Apache::lonhomework::results{"resource.$id.hinttries"} = &Apache::lonnet::EXT("resource.$id.hinttries"); + $Apache::lonhomework::results{"resource.$id.version"} = &Apache::lonnet::usedversion(); + $Apache::lonhomework::results{"resource.$id.maxtries"} = &Apache::lonnet::EXT("resource.$id.maxtries"); } sub find_which_previous { @@ -1364,7 +1657,7 @@ sub grade { } sub get_grade_messages { - my ($id,$prefix,$target,$status,$nocorrect) = @_; + my ($id,$prefix,$target,$status,$nocorrect,$tdclass) = @_; # nocorrect suppresses "Computer's answer now shown above" my ($message,$latemessage,$trystr,$previousmsg); my $showbutton = 1; @@ -1379,13 +1672,17 @@ sub get_grade_messages { &Apache::lonxml::debug('Getting message'); ($showbutton,my $css_class,$message,$previousmsg) = &decideoutput($award,$awarded,$awardmsg,$solved,$previous, - $target,(($status eq 'CAN_ANSWER') || $nocorrect)); + $target,(($status eq 'CAN_ANSWER') || $nocorrect),$tdclass); if ($target eq 'tex') { $message='\vskip 2 mm '.$message.' '; } else { - $message="$message"; + if ($message) { + $message="$message"; + } else { + $message=""; + } if ($previousmsg) { - $previousmsg="$previousmsg"; + $previousmsg="$previousmsg"; } } } @@ -1397,28 +1694,36 @@ sub get_grade_messages { if ( $tries eq '' ) { $tries = '0'; } if ( $maxtries eq '' ) { $maxtries = '2'; } if ( $maxtries eq 'con_lost' ) { $maxtries = '0'; } - my $tries_text= &get_tries_text();; + my $tries_text= &get_tries_text(); if ($showbutton) { if ($target eq 'tex') { if ($env{'request.state'} ne "construct" && $Apache::lonhomework::type ne 'exam' && $env{'form.suppress_tries'} ne 'yes') { - $trystr = ' {\vskip 1 mm \small \textit{'.$tries_text.'} '. - $tries.'/'.$maxtries.'} \vskip 2 mm '; + $trystr ='{\vskip 1 mm \small ' + .&mt('[_1]'.$tries_text.'[_2] [_3]' + ,'\textit{','}',$tries.'/'.$maxtries ) + .'} \vskip 2 mm'; } else { $trystr = '\vskip 0 mm '; } } else { - $trystr = ''.&mt($tries_text)." $tries"; + my $trial =$tries; if ($Apache::lonhomework::parsing_a_task) { } elsif($env{'request.state'} ne 'construct') { - $trystr.="/".&Apache::lonhtmlcommon::direct_parm_link($maxtries,$env{'request.symb'},'maxtries',$id,$target); + $trial.="/".&Apache::lonhtmlcommon::direct_parm_link($maxtries,$env{'request.symb'},'maxtries',$id,$target); } else { if (defined($Apache::inputtags::params{'maxtries'})) { - $trystr.="/".$Apache::inputtags::params{'maxtries'}; + $trial.="/".$Apache::inputtags::params{'maxtries'}; } } - $trystr.=""; + + unless (($env{'request.state'} ne "construct") && + ($env{'course.'.$env{'request.course.id'}.'.type'} eq 'Placement') && + (!$env{'request.role.adv'})) { + $trystr = ''.&mt($tries_text.' [_1]',$trial).''; + } + $trystr = ''.$trystr.''; } } @@ -1426,7 +1731,7 @@ sub get_grade_messages { #last submissions was after due date $latemessage=&mt(' The last submission was after the Due Date ');; if ($target eq 'web') { - $latemessage=''.$latemessage.''; + $latemessage=''.$latemessage.''; } } return ($previousmsg,$latemessage,$message,$trystr,$showbutton); @@ -1440,6 +1745,7 @@ sub gradestatus { my $trystr=''; my $button=''; my $previousmsg=''; + my $tdclass=''; my $status = $Apache::inputtags::status['-1']; &Apache::lonxml::debug("gradestatus has :$status:"); @@ -1447,23 +1753,39 @@ sub gradestatus { && $status ne 'UNAVAILABLE' && $status ne 'INVALID_ACCESS' && $status ne 'NEEDS_CHECKIN' - && $status ne 'NOT_IN_A_SLOT') { + && $status ne 'NOT_IN_A_SLOT' + && $status ne 'RESERVABLE' + && $status ne 'RESERVABLE_LATER' + && $status ne 'NOTRESERVABLE' + && $status ne 'NEED_DIFFERENT_IP') { + + if ($status eq 'SHOW_ANSWER') { + $showbutton = 0; + } + + unless (($status eq 'SHOW_ANSWER') || ($status eq 'CANNOT_ANSWER')) { + if ($target ne 'tex') { + $tdclass = 'LC_status_submit_'.$id; + } + } ($previousmsg,$latemessage,$message,$trystr) = &get_grade_messages($id,"resource.$id",$target,$status, - $showbutton); - if ( $status eq 'SHOW_ANSWER' || $status eq 'CANNOT_ANSWER') { + $showbutton,$tdclass); + if ($status eq 'CANNOT_ANSWER') { $showbutton = 0; } if ( $status eq 'SHOW_ANSWER') { undef($previousmsg); } - if ( $showbutton ) { + if ( $showbutton ) { if ($target ne 'tex') { $button = ''; + type="submit" name="submit_'.$id.'" id="submit_'.$id.'" class="LC_hwk_submit" + value="'.&mt('Submit Answer').'" /> '. + ''; } } @@ -1477,8 +1799,10 @@ sub gradestatus { } else { $output = ''.$output; - if (!$no_previous) { - $output.=''; + if ((!$no_previous) && + (($env{'course.'.$env{'request.course.id'}.'.type'} ne 'Placement') || + ($env{'request.role.adv'}))) { + $output.=''; } $output.= '
'.$button.''.&previous_tries($id,$target).''.&previous_tries($id,$target).'
'; return $output; @@ -1493,14 +1817,15 @@ sub previous_tries { my $count; my %count_lookup; - my $lastrndseed; + my ($lastrndseed,$lasttype); + my $numstamps = 0; foreach my $i (1..$Apache::lonhomework::history{'version'}) { my $prefix = $i.":resource.$id"; - my $is_anon; + my $is_anon; + my $curr_type = $Apache::lonhomework::history{"$prefix.type"}; if (defined($env{'form.grade_symb'})) { - if (($Apache::lonhomework::history{"$prefix.type"} eq 'anonsurvey') || - ($Apache::lonhomework::history{"$prefix.type"} eq 'anonsurveycred')) { + if (($curr_type eq 'anonsurvey') || ($curr_type eq 'anonsurveycred')) { $is_anon = 1; } } @@ -1539,8 +1864,9 @@ sub previous_tries { {$1 $txt_correct. $3}s; } my $trystr = "(".&mt('Try [_1]',$Apache::lonhomework::history{"$prefix.tries"}).")"; - if ($curr_rndseed || $lastrndseed) { - if ($curr_rndseed ne $lastrndseed) { + if (($curr_rndseed ne '') && ($lastrndseed ne '')) { + if (($curr_rndseed ne $lastrndseed) && + (($curr_type eq 'randomizetry') || ($lasttype eq 'randomizetry'))) { $trystr .= '
'.&mt('New problem variation this try.').''; } } @@ -1550,10 +1876,17 @@ sub previous_tries { $message =~ s{()}{}; - $output.=''; - $output.=''.$count.''; - $output.=$message; - + $output .= ''. + ''.$count.''.$message; + if ((!$is_anon) && ($Apache::lonhomework::history{"$prefix.tries"}) && + ($Apache::lonhomework::history{"$prefix.award"} ne 'ASSIGNED_SCORE') && + ($Apache::lonhomework::history{$i.':timestamp'})) { + $output .= ''.&Apache::lonlocal::locallocaltime( + $Apache::lonhomework::history{$i.':timestamp'}).''; + $numstamps ++; + } else { + $output .= ''; + } foreach my $resid (@Apache::inputtags::response) { my $prefix = $prefix.".$resid"; if (exists($Apache::lonhomework::history{"$prefix.submission"})) { @@ -1574,38 +1907,38 @@ sub previous_tries { } $output.=&Apache::loncommon::end_data_table_row()."\n"; $lastrndseed = $curr_rndseed; + $lasttype = $curr_type; } return if ($output eq ''); - my $headers = - ''.''.&mt('Submission #').''.&mt('Try'). - ''. - &mt('Submitted Answer').''; + my $headers = ''. + ''.&mt('Submission #').''. + ''.&mt('Try').''; + if ($numstamps) { + $headers .= &mt('When'); + } + $headers .= ''; + my $colspan = scalar(@Apache::inputtags::response); + if ($colspan > 1) { + $headers .= ''; + } else { + $headers .= ''; + } + $headers .= &mt('Submitted Answer').''; $output =''.$headers.$output.'
'; - #return $output; - $output = &Apache::loncommon::js_ready($output); - $output.='
'; - my $windowopen=&Apache::lonhtmlcommon::javascript_docopen(); my $tries_text = &get_tries_text('link'); - my $start_page = - &Apache::loncommon::start_page($tries_text, undef, - {'only_body' => 1, - 'bgcolor' => '#FFFFFF', - 'js_ready' => 1, - 'inherit_jsmath' => 1, }); - my $end_page = - &Apache::loncommon::end_page({'js_ready' => 1,}); my $prefix = $env{'form.request.prefix'}; $prefix =~ tr{.}{_}; - my $function_name = "LONCAPA_previous_tries_".$prefix. - $Apache::lonxml::curdepth.'_'.$env{'form.counter'}; - my $result ="".&mt($tries_text)."
"; - #use Data::Dumper; - #&Apache::lonnet::logthis(&Dumper(\%Apache::inputtags::submission_display)); + my $function_name = 'LONCAPA_previous_tries_'.$prefix; + if (($env{'request.state'} eq 'construct') || ($id =~ /\W/)) { + $function_name .= $Apache::lonxml::curdepth; + } else { + $function_name .= $id; + } + $function_name .= '_'.$Apache::lonxml::counter; + my $possmathjax = 1; + my $result = &Apache::loncommon::modal_adhoc_window($function_name,420,410,$output, + &mt($tries_text),$possmathjax)."
"; return $result; } @@ -1631,6 +1964,133 @@ sub get_tries_text { return $tries_text; } +sub spelling_languages { + my %langchoices; + foreach my $id (&Apache::loncommon::languageids()) { + my $code = &Apache::loncommon::supportedlanguagecode($id); + if ($code ne '') { + $langchoices{$code} = &Apache::loncommon::plainlanguagedescription($id); + } + } + my @spelllangs = ('none'); + foreach my $code ('en','de','he','es','fr','pt','tr') { + push(@spelllangs,[$code,$langchoices{$code}]); + } + return \@spelllangs; +} + +sub edit_mathresponse_button { + my ($field) = @_; + my $eqneditor = 'lcmath'; + if ($env{'browser.type'} eq 'safari') { + if ($env{'browser.os'} eq 'mac') { + my ($prefix,$version) = ($env{'browser.version'} =~ /^(\d*)(\d{3})\./); + if ($env{'browser.mobile'}) { + if (($version < 531) || (($prefix eq '') && ($version < 533))) { + $eqneditor = ''; + } + } elsif ($version < 533) { + $eqneditor = 'dragmath'; + } + } elsif ($env{'browser.os'} eq 'win') { + if ($env{'browser.version'} < 533) { + $eqneditor = 'dragmath'; + } + } + } elsif ($env{'browser.type'} eq 'explorer') { + if ($env{'browser.version'} < 9) { + $eqneditor = 'dragmath'; + } + } elsif ($env{'browser.type'} eq 'mozilla') { + if ($env{'browser.version'} < 5) { + $eqneditor = 'dragmath'; + } else { + if ($env{'browser.info'} =~ /^firefox\-([\d\.]+)/) { + my $firefox = $1; + if ($firefox < 4) { + $eqneditor = 'dragmath'; + } + } + } + } elsif ($env{'browser.type'} eq 'chrome') { + if ($env{'browser.version'} < 5) { + $eqneditor = 'dragmath'; + } + } elsif ($env{'browser.type'} eq 'opera') { + if ($env{'browser.version'} < 12) { + $eqneditor = 'dragmath'; + } + } + if ($eqneditor eq 'lcmath') { + if (($env{'request.course.id'}) && ($env{'request.state'} ne 'construct')) { + if (exists($env{'course.'.$env{'request.course.id'}.'.uselcmath'})) { + if ($env{'course.'.$env{'request.course.id'}.'.uselcmath'} eq '0') { + $eqneditor = 'dragmath'; + } + } else { + my %domdefs = &Apache::lonnet::get_domain_defaults($env{'course.'.$env{'request.course.id'}.'.domain'}); + if ($domdefs{'uselcmath'} eq '0') { + $eqneditor = 'dragmath'; + } + } + } else { + my %domdefs = &Apache::lonnet::get_domain_defaults($env{'course.'.$env{'request.course.id'}.'.domain'}); + if ($domdefs{'uselcmath'} eq '0') { + $eqneditor = 'dragmath'; + } + } + } + if ($eqneditor eq 'dragmath') { + # DragMath applet + my $button=&mt('Edit Answer'); +# my $helplink=&Apache::loncommon::help_open_topic('Formula_Editor'); + my $iconpath=$Apache::lonnet::perlvar{'lonIconsURL'}; + return(< +function LC_mathedit_${field} (LCtextline) { + thenumber = LCtextline; + var thedata = ''; + if (document.getElementById(LCtextline)) { + thedata = document.getElementById(LCtextline).value; + } + newwin = window.open("/adm/dragmath/MaximaPopup.html","","width=565,height=400,resizable"); +} + +$button +ENDFORMULABUTTON + } elsif ($eqneditor eq 'lcmath') { + # LON-CAPA math equation editor + my $mathjaxjs; + unless (lc(&Apache::lontexconvert::tex_engine()) eq 'mathjax') { + $mathjaxjs = <<"MATHJAX_SCRIPT"; +var mathjaxscript = document.createElement("script"); + mathjaxscript.type = "text/javascript"; + mathjaxscript.src = "/adm/MathJax/MathJax.js?config=TeX-AMS-MML_HTMLorMML"; + document.body.appendChild(mathjaxscript); +MATHJAX_SCRIPT + } + return(< + var LCmathField = document.getElementById('${field}'); + LCmathField.className += ' math'; // note the space + LCmathField.setAttribute('data-implicit_operators', 'true'); + var LCMATH_started; + if (typeof LCMATH_started === 'undefined') { + $mathjaxjs + LCMATH_started = true; + var script = document.createElement("script"); + script.type = "text/javascript"; + script.src = "/adm/LC_math_editor/LC_math_editor.min.js"; + document.body.appendChild(script); + window.addEventListener('load', function(e) { + LCMATH.initEditors(); + }, false); + } + +EQ_EDITOR_SCRIPT + } +} + 1; __END__ 500 Internal Server Error

Internal Server Error

The server encountered an internal error or misconfiguration and was unable to complete your request.

Please contact the server administrator at root@localhost to inform them of the time this error occurred, and the actions you performed just before this error.

More information about this error may be available in the server error log.