--- loncom/homework/inputtags.pm 2011/06/06 23:28:42 1.290 +++ loncom/homework/inputtags.pm 2014/06/19 19:37:35 1.324 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # input definitons # -# $Id: inputtags.pm,v 1.290 2011/06/06 23:28:42 www Exp $ +# $Id: inputtags.pm,v 1.324 2014/06/19 19:37:35 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -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,19 @@ sub start_textfield { if ( $rows eq '') { $rows = 16; } my $addchars=&Apache::lonxml::get_param('addchars',$parstack,$safeeval); $result=''; + my $tagident = 'HWVAL_' . $resid; if ($addchars) { - $result.=&addchars('HWVAL_'.$resid,$addchars); + $result.=&addchars($tagident, $addchars); } - my $textareaclass = 'class="LC_richDetectHtml"'; - $result.= '"; + my $resid = $Apache::inputtags::response[-1]; + my $tagident = 'HWVAL_' . $resid; + my $result = ""; + $result .= &spellcheck_onblur($tagident, $spellcheck); + return $result; } } elsif ($target eq 'edit') { $result=&Apache::edit::end_table(); @@ -330,6 +393,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 +421,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]; @@ -380,8 +460,15 @@ sub start_textline { if ($Apache::inputtags::status[-1] eq 'CANNOT_ANSWER') { $name = "none"; } - $result.= ''; + $result.= ''; + + $result .= &spellcheck_onblur($name, $spellcheck); } if ($Apache::lonhomework::type eq 'exam' && &needs_exam_box($tagstack)) { @@ -400,12 +487,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') { @@ -562,7 +652,7 @@ 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) { @@ -571,13 +661,25 @@ sub file_selector { if ($which eq 'uploadonly' || $which eq 'both') { $result.=&mt('Submit a file: (only one file per submission)'). '

'; + $jspart.'_'.$id.'" id="HWFILE'.$jspart.'_'.$id.'" />
'; } 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)').'
'. ''. '
'; @@ -594,7 +696,8 @@ 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 $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?').''; @@ -660,13 +763,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(); @@ -676,9 +790,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 = ''. @@ -719,6 +835,43 @@ 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', @@ -885,8 +1038,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 { @@ -911,7 +1064,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') { @@ -983,7 +1142,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') { @@ -993,7 +1152,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') { @@ -1070,6 +1229,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'}; @@ -1120,7 +1280,17 @@ 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"); + unless (($due_date) && ($due_date < $first_access + $interval[0])) { + $message = &mt("Answer Submitted: Your final submission will be graded when the time limit is reached."); + } + } + } $css_class=$possible_class{'no_grade'}; $button=1; } @@ -1436,28 +1606,30 @@ 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.=""; + $trystr = ''.&mt($tries_text.' [_1]',$trial).''; } } @@ -1486,12 +1658,19 @@ 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') { + + if ($status eq 'SHOW_ANSWER') { + $showbutton = 0; + } ($previousmsg,$latemessage,$message,$trystr) = &get_grade_messages($id,"resource.$id",$target,$status, $showbutton); - if ( $status eq 'SHOW_ANSWER' || $status eq 'CANNOT_ANSWER') { + if ($status eq 'CANNOT_ANSWER') { $showbutton = 0; } if ( $status eq 'SHOW_ANSWER') { @@ -1533,6 +1712,7 @@ sub previous_tries { my $count; my %count_lookup; my $lastrndseed; + my $numstamps = 0; foreach my $i (1..$Apache::lonhomework::history{'version'}) { my $prefix = $i.":resource.$id"; @@ -1578,7 +1758,7 @@ 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 || $lastrndseed) && ($i > 1)) { if ($curr_rndseed ne $lastrndseed) { $trystr .= '
'.&mt('New problem variation this try.').''; } @@ -1589,10 +1769,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"})) { @@ -1615,36 +1802,28 @@ sub previous_tries { $lastrndseed = $curr_rndseed; } 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 $result = &Apache::loncommon::modal_adhoc_window($function_name,420,410,$output,&mt($tries_text))."
"; return $result; } @@ -1670,6 +1849,21 @@ 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; +} + 1; __END__