--- loncom/homework/structuretags.pm 2006/04/15 01:06:59 1.346
+++ loncom/homework/structuretags.pm 2015/12/10 16:26:43 1.543
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# definition of tags that give a structure to a document
#
-# $Id: structuretags.pm,v 1.346 2006/04/15 01:06:59 albertel Exp $
+# $Id: structuretags.pm,v 1.543 2015/12/10 16:26:43 damieng Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -27,6 +27,29 @@
#
###
+=pod
+
+=head1 NAME
+
+Apache::structuretags
+
+=head1 SYNOPSIS
+
+
+This is part of the LearningOnline Network with CAPA project
+described at http://www.lon-capa.org.
+
+
+=head1 NOTABLE SUBROUTINES
+
+=over
+
+=item
+
+=back
+
+=cut
+
package Apache::structuretags;
@@ -36,17 +59,131 @@ use Apache::File();
use Apache::lonmenu;
use Apache::lonlocal;
use Apache::lonxml;
+use Apache::londefdef;
use Apache::lonenc();
+use Apache::loncommon();
use Time::HiRes qw( gettimeofday tv_interval );
+use lib '/home/httpd/lib/perl/';
+use LONCAPA;
+
BEGIN {
- &Apache::lonxml::register('Apache::structuretags',('block','languageblock','instructorcomment','while','randomlist','problem','library','web','tex','part','preduedate','postanswerdate','solved','notsolved','problemtype','startouttext','endouttext','simpleeditbutton','definetag'));
+ &Apache::lonxml::register('Apache::structuretags',('block','languageblock','translated','instructorcomment','while','randomlist','problem','library','web','tex','part','preduedate','postanswerdate','solved','notsolved','problemtype','startpartmarker','startouttext','endpartmarker','endouttext','simpleeditbutton','definetag'));
}
+
+#---------------------------------------------------------------------------------
+#
+# This section of code deals with hyphenation management.
+# We must do three things:
+# - keep track fo the desired languages to alter the header.
+# - provide hyphenation selection as needed by each language that appears in the
+# text.
+# - Provide the header text needed to make available the desired hyphenations.
+#
+#
+
+# Hash whose keys are the languages encountered in the document/resource.
+#
+
+my %languages_required;
+##
+# Given a language selection as input returns a chunk of LaTeX that
+# selects the required hyphenator.
+#
+# @param language - the language being selected.
+# @return string
+# @retval The LaTeX needed to select the hyphenation appropriate to the language.
+#
+sub select_hyphenation {
+ my $language = shift;
+
+ $language = &Apache::loncommon::latexlanguage($language); # Translate -> latex language.
+
+ # If there is no latex language there's not much we can do:
+
+ if ($language) {
+ &require_language($language);
+ my $babel_hyphenation = "\\selectlanguage{$language}";
+
+ return $babel_hyphenation;
+ } else {
+ return '';
+ }
+}
+##
+# Selects hyphenation based on the current problem metadata.
+# This requires that
+# - There is a language metadata item set for the problem.
+# - The language has a latex/babel hyphenation.
+#
+# @note: Uses &Apache::lonxml::request to locate the Uri associated with
+# this problem.
+# @return string (possibly empty).
+# @retval If not empty an appropriate \selectlanguage{} directive.
+#
+sub select_metadata_hyphenation {
+ my $uri = $Apache::lonxml::request->uri;
+ my $language = &Apache::lonnet::metadata($uri, 'language');
+ my $latex_language = &Apache::loncommon::latexhyphenation($language);
+ if ($latex_language) {
+ return '\selectlanguage{'.$latex_language."}\n";
+ }
+ return ''; # no latex hyphenation or no lang metadata.
+}
+
+
+##
+# Clears the set of languages required by the document being rendered.
+#
+sub clear_required_languages {
+ %languages_required = ();
+}
+##
+# Allows an external client of this module to register a need for a language:
+#
+# @param LaTeX language required:
+#
+sub require_language {
+ my $language = shift;
+ $languages_required{$language} = 1;
+}
+
+##
+# Provides the header for babel that indicates the languages
+# the document requires.
+# @return string
+# @retval \usepackage[lang1,lang2...]{babel}
+# @retval '' if there are no languages_required.
+sub languages_header {
+ my $header ='';
+ my @languages = (keys(%languages_required));
+
+ # Only generate the header if there are languages:
+
+ if (scalar @languages) {
+ my $language_list = join(',', (@languages));
+ $header = '\usepackage['.$language_list."]{babel}\n";
+ }
+ return $header;
+}
+
+#----------------------------------------------------------------------------------
+
sub start_web {
my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
- my $bodytext=&Apache::lonxml::get_all_text("/web",$parser,$style);
- if ($target eq 'web' || $target eq 'webgrade') {
- return $bodytext;
+ if ($target ne 'edit' && $target ne 'modified') {
+ my $bodytext=&Apache::lonxml::get_all_text("/web",$parser,$style);
+ if ($target eq 'web' || $target eq 'webgrade') {
+ return $bodytext;
+ }
+ } elsif ($target eq "edit" ) {
+ my $bodytext =
+ &Apache::lonxml::get_all_text_unbalanced("/web",$parser);
+ my $result = &Apache::edit::tag_start($target,$token);
+ $result .= &Apache::edit::editfield($token->[1],$bodytext,'',80,1);
+ return $result;
+ } elsif ( $target eq "modified" ) {
+ return $token->[4].&Apache::edit::modifiedfield("/web",$parser);
}
return '';
}
@@ -58,9 +195,26 @@ sub end_web {
sub start_tex {
my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
my $result='';
- my $bodytext=&Apache::lonxml::get_all_text("/tex",$parser,$style);
- if ($target eq 'tex') {
- return $bodytext.' ';
+ if ($target ne 'edit' && $target ne 'modified') {
+ my $bodytext=&Apache::lonxml::get_all_text("/tex",$parser,$style);
+ if ($target eq 'tex') {
+
+ # If inside a table, occurrences of \\ must be removed;
+ # else the table blows up.
+
+ if (&Apache::londefdef::is_inside_of($tagstack, "table")) {
+ $bodytext =~ s/\\\\//g;
+ }
+ return $bodytext.'{}';
+ }
+ } elsif ($target eq "edit" ) {
+ my $bodytext =
+ &Apache::lonxml::get_all_text_unbalanced("/tex",$parser);
+ my $result = &Apache::edit::tag_start($target,$token);
+ $result .= &Apache::edit::editfield($token->[1],$bodytext,'',80,1);
+ return $result;
+ } elsif ( $target eq "modified" ) {
+ return $token->[4].&Apache::edit::modifiedfield("/tex",$parser);
}
return $result;;
}
@@ -69,6 +223,181 @@ sub end_tex {
return '';
}
+sub homework_js {
+ my ($postsubmit,$timeout);
+ if (($env{'request.course.id'}) && ($env{'request.state'} ne 'construct')) {
+ my $crstype;
+ if (&Apache::loncommon::course_type() eq 'Community') {
+ $crstype = 'community';
+ } else {
+ if ($env{'course.'.$env{'request.course.id'}.'.internal.coursecode'}) {
+ $crstype = 'official';
+ } elsif ($env{'course.'.$env{'request.course.id'}.'.internal.textbook'}) {
+ $crstype = 'textbook';
+ } else {
+ $crstype = 'unofficial';
+ }
+ }
+ $postsubmit = $env{'course.'.$env{'request.course.id'}.'.internal.postsubmit'};
+ if ($postsubmit eq '') {
+ my %domdefs = &Apache::lonnet::get_domain_defaults($env{'course.'.$env{'request.course.id'}.'.domain'});
+ $postsubmit = $domdefs{'postsubmit'};
+ unless ($postsubmit eq 'off') {
+ $timeout = $domdefs{$crstype.'postsubtimeout'};
+ }
+ } elsif ($postsubmit eq '0') {
+ $postsubmit = 'off';
+ } elsif ($postsubmit eq '1') {
+ $postsubmit = 'on';
+ $timeout = $env{'course.'.$env{'request.course.id'}.'.internal.postsubtimeout'};
+ if ($timeout eq '') {
+ my %domdefs = &Apache::lonnet::get_domain_defaults($env{'course.'.$env{'request.course.id'}.'.domain'});
+ $timeout = $domdefs{$crstype.'postsubtimeout'};
+ }
+ }
+ if ($timeout eq '') {
+ $timeout = 60;
+ }
+ } else {
+ my %domdefs = &Apache::lonnet::get_domain_defaults($env{'request.role.domain'});
+ $postsubmit = $domdefs{'postsubmit'};
+ unless ($postsubmit eq 'off') {
+ $timeout = 60;
+ }
+ }
+ my $jstimeout = 0;
+ if ($timeout) {
+ $jstimeout = 1000 * $timeout;
+ }
+ return &Apache::loncommon::resize_textarea_js().
+ &Apache::loncommon::colorfuleditor_js().
+ &setmode_javascript().
+ <<"JS";
+
+JS
+}
+
+sub setmode_javascript {
+ return <<"ENDSCRIPT";
+
+ENDSCRIPT
+}
+
sub page_start {
my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$name,
$extra_head)=@_;
@@ -79,13 +408,94 @@ sub page_start {
}
}
-
if ($target eq 'tex') {
return
&Apache::londefdef::start_html($target,$token,$tagstack,
$parstack,$parser,$safeeval);
}
+ $extra_head .= &homework_js().
+ &Apache::lonhtmlcommon::dragmath_js("EditMathPopup");
+ if (&Apache::lonhtmlcommon::htmlareabrowser()) {
+ my %textarea_args = (
+ dragmath => 'math',
+ );
+ $extra_head .= &Apache::lonhtmlcommon::htmlareaselectactive(\%textarea_args);
+ }
+ my $is_task = ($env{'request.uri'} =~ /\.task$/);
+ my ($needs_upload,$partlist);
+ my ($symb)= &Apache::lonnet::whichuser();
+ my ($map,$resid,$resurl)=&Apache::lonnet::decode_symb($symb);
+ if ($is_task) {
+ $extra_head .= &Apache::lonhtmlcommon::file_submissionchk_js();
+ } else {
+ if (&Apache::lonnet::EXT("resource.$Apache::inputtags::part.uploadedfiletypes") ne '') {
+ unless ($env{'request.state'} eq 'construct') {
+ my $navmap = Apache::lonnavmaps::navmap->new();
+ if (ref($navmap)) {
+ my $mapres = $navmap->getResourceByUrl($map);
+ my $is_page;
+ if (ref($mapres)) {
+ $is_page = $mapres->is_page();
+ }
+ unless ($is_page) {
+ $needs_upload = 1;
+ }
+ if ((ref($tagstack) eq 'ARRAY') && ($tagstack->[-1] eq 'problem')) {
+ my $res = $navmap->getBySymb($symb);
+ if (ref($res)) {
+ $partlist = $res->parts();
+ }
+ }
+ }
+ }
+ } else {
+ unless ($env{'request.state'} eq 'construct') {
+ my $navmap = Apache::lonnavmaps::navmap->new();
+ if (ref($navmap)) {
+ my $mapres = $navmap->getResourceByUrl($map);
+ my $is_page;
+ if (ref($mapres)) {
+ $is_page = $mapres->is_page();
+ }
+ if ($is_page) {
+ if ((ref($tagstack) eq 'ARRAY') && ($tagstack->[-1] eq 'problem')) {
+ my $res = $navmap->getBySymb($symb);
+ if (ref($res)) {
+ $partlist = $res->parts();
+ }
+ }
+ } else {
+ my $res = $navmap->getBySymb($symb);
+ if (ref($res)) {
+ $partlist = $res->parts();
+ if (ref($partlist) eq 'ARRAY') {
+ foreach my $part (@{$partlist}) {
+ my @types = $res->responseType($part);
+ my @ids = $res->responseIds($part);
+ for (my $i=0; $i < scalar(@ids); $i++) {
+ if ($types[$i] eq 'essay') {
+ my $partid = $part.'_'.$ids[$i];
+ if (&Apache::lonnet::EXT("resource.$partid.uploadedfiletypes") ne '') {
+ $needs_upload = 1;
+ last;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ if ($needs_upload) {
+ $extra_head .= &Apache::lonhtmlcommon::file_submissionchk_js()
+ .'';
+ }
+ }
+
my %body_args;
if (defined($found{'html'})) {
$body_args{'skip_phases'}{'head'}=1;
@@ -93,28 +503,45 @@ sub page_start {
$extra_head .= &Apache::lonhtmlcommon::spellheader();
- my $css_href = &Apache::lonnet::EXT('resource.0.cssfile');
- if ($css_href =~ /\S/) {
- &Apache::lonxml::extlink($css_href);
- $extra_head .=
- '';
- }
- if ($target eq 'edit') {
+ $extra_head .= &Apache::londefdef::generate_css_links();
+
+ if ($env{'request.state'} eq 'construct') {
$extra_head.=&Apache::edit::js_change_detection().
"\n";
+ if ($target eq 'edit') {
+ $extra_head .= &Apache::edit::js_update_linknum();
+ }
}
}
+ my $pageheader = '';
if (defined($found{'body'})) {
$body_args{'skip_phases'}{'body'}=1;
} elsif (!defined($found{'body'})
&& $env{'request.state'} eq 'construct') {
if ($target eq 'web' || $target eq 'edit') {
- # no extra args to bodytag
- }
+ unless ($env{'form.inhibitmenu'} eq 'yes') {
+ # Breadcrumbs for Authoring Space
+ &Apache::lonhtmlcommon::clear_breadcrumbs();
+ &Apache::lonhtmlcommon::add_breadcrumb({
+ 'text' => 'Authoring Space',
+ 'href' => &Apache::loncommon::authorspace($env{'request.uri'}),
+ });
+ # breadcrumbs (and tools) will be created
+ # in start_page->bodytag->innerregister
+
+# FIXME Where are we?
+# &Apache::lonhtmlcommon::add_breadcrumb({
+# 'text' => 'Problem Editing', # 'Problem Testing'
+# 'href' => '',
+# });
+ $pageheader = &Apache::loncommon::head_subbox(
+ &Apache::loncommon::CSTR_pageheader());
+ }
+ }
} elsif (!defined($found{'body'})) {
my %add_entries;
my $background=&Apache::lonxml::get_param('background',$parstack,
@@ -125,71 +552,102 @@ sub page_start {
my $bgcolor=&Apache::lonxml::get_param('bgcolor',$parstack,
$safeeval);
- if ($bgcolor eq '' ) { $bgcolor = '#FFFFFF'; }
+ if ($bgcolor eq '' ) { $bgcolor = '#FFFFFF'; }
- $body_args{'bgcolor'} = $bgcolor;
- $body_args{'no_title'} = 1;
- $body_args{'force_register'} = 1;
- $body_args{'add_entries'} = \%add_entries;
+ $body_args{'bgcolor'} = $bgcolor;
+ # $body_args{'no_title'} = 1;
+ $body_args{'force_register'} = 1;
+ $body_args{'add_entries'} = \%add_entries;
+ if ( $env{'request.state'} eq 'construct') {
+ $body_args{'only_body'} = 1;
+ } elsif ($target eq 'web') {
+ $body_args{'print_suppress'} = 1;
+ }
}
-
+ $body_args{'no_auto_mt_title'} = 1;
my $page_start = &Apache::loncommon::start_page($name,$extra_head,
\%body_args);
-
+ $page_start .= $pageheader;
if (!defined($found{'body'})
&& $env{'request.state'} ne 'construct'
&& ($target eq 'web' || $target eq 'webgrade')) {
- my ($symb,undef,undef,undef,$publicuser)= &Apache::lonxml::whichuser();
- if ($symb eq '' && !$publicuser) {
- my $help = &Apache::loncommon::help_open_topic("Ambiguous_Reference");
- $help=&mt("Browsing resource, all submissions are temporary.")."
";
- $page_start .= $help;
- }
+ my ($symb,undef,undef,undef,$publicuser)= &Apache::lonnet::whichuser();
+ if ($symb eq '' && !$publicuser) {
+ $page_start .= '
' + .&mt('Browsing resource, all submissions are temporary.') + .'
'; + } } - if (!defined($found{'body'})) { + if (!defined($found{'body'}) && $env{'request.state'} ne 'construct') { $page_start .= &Apache::lonxml::message_location(); } - my $form_tag_start; if (!defined($found{'form'})) { $form_tag_start='\n".&Apache::loncommon::end_page(); } @@ -266,31 +846,40 @@ sub option { sub problem_web_to_edit_header { my ($rndseed)=@_; - my $result.=''; + my $result .= '$lt{'id_expln'}
- -$lt{'warning'}
- - ENDCHECKOUT } sub firstaccess_msg { my ($time,$symb)=@_; - my ($map)=&Apache::lonnet::decode_symb($symb); - my $foldertitle=&Apache::lonnet::gettitle($map); - &Apache::lonxml::debug("map is $map title is $foldertitle"); - return (<'.&mt('Unable to determine if this resource is open due to network problems. Please try again later.').'
'; + } elsif ($status eq 'NOT_IN_A_SLOT') { + $msg.=''.&mt('You are not currently signed up to work at this time and/or place.').'
'; + } elsif (($status eq 'RESERVABLE') || ($status eq 'RESERVABLE_LATER') || + ($status eq 'NOTRESERVABLE')) { + $msg.=''.&mt('Access requires reservation to work at specific time/place.').'
'; } elsif ($status ne 'NOT_YET_VIEWED') { - $msg.=''.&mt('Not open to be viewed').'
'; + } if ($status eq 'CLOSED' || $status eq 'INVALID_ACCESS') { - $msg.='The problem '.$accessmsg; + $msg.=&mt('The problem ').$accessmsg; } elsif ($status eq 'UNCHECKEDOUT') { $msg.=&checkout_msg(); } elsif ($status eq 'NOT_YET_VIEWED') { $msg.=&firstaccess_msg($accessmsg,$symb); } elsif ($status eq 'NOT_IN_A_SLOT') { - $msg.=&Apache::bridgetask::add_request_another_attempt_button("Sign up for time to work."); - } + $msg.=&Apache::bridgetask::add_request_another_attempt_button("Sign up for time to work"); + } elsif ($status eq 'RESERVABLE') { + $msg.=&mt('Available to make a reservation.').' '.&mt('Reservation window closes [_1].', + &Apache::lonnavmaps::timeToHumanString($accessmsg,'end')). + '