--- loncom/interface/lonhelper.pm 2003/09/25 20:39:32 1.47 +++ loncom/interface/lonhelper.pm 2005/10/11 21:27:44 1.120 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # .helper XML handler to implement the LON-CAPA helper # -# $Id: lonhelper.pm,v 1.47 2003/09/25 20:39:32 albertel Exp $ +# $Id: lonhelper.pm,v 1.120 2005/10/11 21:27:44 albertel Exp $ # # Copyright Michigan State University Board of Trustees # @@ -25,10 +25,6 @@ # # http://www.lon-capa.org/ # -# (Page Handler -# -# (.helper handler -# =pod @@ -172,12 +168,21 @@ before parsing XML fragments and B # mod_perl connection. In this code, it was manifesting itself in the existence -# of two seperate file-scoped $helper variables, one set to the value of the +# of two separate file-scoped $helper variables, one set to the value of the # helper in the helper constructor, and one referenced by the handler on the # "$helper->process()" line. Using the debugger, one could actually # see the two different $helper variables, as hashes at completely @@ -247,7 +252,7 @@ sub real_handler { my $r = shift; my $uri = shift; if (!defined($uri)) { $uri = $r->uri(); } - $ENV{'request.uri'} = $uri; + $env{'request.uri'} = $uri; my $filename = '/home/httpd/html' . $uri; my $fh = Apache::File->new($filename); my $file; @@ -255,21 +260,13 @@ sub real_handler { # Send header, don't cache this page - if ($r->header_only) { - if ($ENV{'browser.mathml'}) { - $r->content_type('text/xml'); - } else { - $r->content_type('text/html'); - } - $r->send_http_header; - return OK; - } - if ($ENV{'browser.mathml'}) { - $r->content_type('text/xml'); + if ($env{'browser.mathml'}) { + &Apache::loncommon::content_type($r,'text/xml'); } else { - $r->content_type('text/html'); + &Apache::loncommon::content_type($r,'text/html'); } $r->send_http_header; + return OK if $r->header_only; $r->rflush(); # Discard result, we just want the objects that get created by the @@ -278,7 +275,7 @@ sub real_handler { my $allowed = $helper->allowedCheck(); if (!$allowed) { - $ENV{'user.error.msg'} = $ENV{'request.uri'}.':'.$helper->{REQUIRED_PRIV}. + $env{'user.error.msg'} = $env{'request.uri'}.':'.$helper->{REQUIRED_PRIV}. ":0:0:Permission denied to access this helper."; return HTTP_NOT_ACCEPTABLE; } @@ -359,9 +356,11 @@ sub end_state { package Apache::lonhelper::helper; use Digest::MD5 qw(md5_hex); -use HTML::Entities; +use HTML::Entities(); use Apache::loncommon; use Apache::File; +use Apache::lonlocal; +use Apache::lonnet; sub new { my $proto = shift; @@ -373,16 +372,16 @@ sub new { # If there is a state from the previous form, use that. If there is no # state, use the start state parameter. - if (defined $ENV{"form.CURRENT_STATE"}) + if (defined $env{"form.CURRENT_STATE"}) { - $self->{STATE} = $ENV{"form.CURRENT_STATE"}; + $self->{STATE} = $env{"form.CURRENT_STATE"}; } else { $self->{STATE} = "START"; } - $self->{TOKEN} = $ENV{'form.TOKEN'}; + $self->{TOKEN} = $env{'form.TOKEN'}; # If a token was passed, we load that in. Otherwise, we need to create a # new storage file # Tried to use standard Tie'd hashes, but you can't seem to take a @@ -415,16 +414,16 @@ sub new { return undef; } # Must create the storage - $self->{TOKEN} = md5_hex($ENV{'user.name'} . $ENV{'user.domain'} . + $self->{TOKEN} = md5_hex($env{'user.name'} . $env{'user.domain'} . time() . rand()); $self->{FILENAME} = $Apache::lonnet::tmpdir . md5_hex($self->{TOKEN}); } # OK, we now have our persistent storage. - if (defined $ENV{"form.RETURN_PAGE"}) + if (defined $env{"form.RETURN_PAGE"}) { - $self->{RETURN_PAGE} = $ENV{"form.RETURN_PAGE"}; + $self->{RETURN_PAGE} = $env{"form.RETURN_PAGE"}; } else { @@ -453,11 +452,11 @@ sub _saveVars { my $self = shift; my $result = ""; $result .= '\n"; + HTML::Entities::encode($self->{STATE},'<>&"') . "\" />\n"; $result .= '\n"; $result .= '\n"; + HTML::Entities::encode($self->{RETURN_PAGE},'<>&"') . "\" />\n"; return $result; } @@ -485,11 +484,11 @@ sub declareVar { } my $envname = 'form.' . $var . '.forminput'; - if (defined($ENV{$envname})) { - if (ref($ENV{$envname})) { - $self->{VARS}->{$var} = join('|||', @{$ENV{$envname}}); + if (defined($env{$envname})) { + if (ref($env{$envname})) { + $self->{VARS}->{$var} = join('|||', @{$env{$envname}}); } else { - $self->{VARS}->{$var} = $ENV{$envname}; + $self->{VARS}->{$var} = $env{$envname}; } } } @@ -501,7 +500,7 @@ sub allowedCheck { return 1; } - return Apache::lonnet::allowed($self->{REQUIRED_PRIV}, $ENV{'request.course.id'}); + return Apache::lonnet::allowed($self->{REQUIRED_PRIV}, $env{'request.course.id'}); } sub changeState { @@ -523,7 +522,7 @@ sub process { # Phase 1: Post processing for state of previous screen (which is actually # the "current state" in terms of the helper variables), if it wasn't the # beginning state. - if ($self->{STATE} ne "START" || $ENV{"form.SUBMIT"} eq "Next ->") { + if ($self->{STATE} ne "START" || $env{"form.SUBMIT"} eq &mt("Next ->")) { my $prevState = $self->{STATES}{$self->{STATE}}; $prevState->postprocess(); } @@ -574,13 +573,19 @@ sub display { } # Phase 4: Display. - my $stateTitle = $state->title(); - my $bodytag = &Apache::loncommon::bodytag("$self->{TITLE}",'',''); + my $html=&Apache::lonxml::xmlbegin(); + my $stateTitle=&mt($state->title()); + my $helperTitle = &mt($self->{TITLE}); + my $bodytag = &Apache::loncommon::bodytag($helperTitle,'',''); + my $previous = HTML::Entities::encode(&mt("<- Previous"), '<>&"'); + my $next = HTML::Entities::encode(&mt("Next ->"), '<>&"'); + # FIXME: This should be parameterized, not concatenated - Jeremy + my $loncapaHelper = &mt("LON-CAPA Helper:"); $result .= < +$html - LON-CAPA Helper: $self->{TITLE} + $loncapaHelper: $helperTitle $bodytag HEADER @@ -607,12 +612,12 @@ HEADER } if ($self->{DONE}) { my $returnPage = $self->{RETURN_PAGE}; - $result .= "End Helper"; + $result .= "" . &mt("End Helper") . ""; } else { $result .= ' '; + $result .= ''; } } @@ -626,12 +631,12 @@ HEADER } if ($self->{DONE}) { my $returnPage = $self->{RETURN_PAGE}; - $result .= "End Helper"; + $result .= "" . &mt('End Helper') . ""; } else { $result .= ' '; + $result .= ''; } } @@ -883,6 +888,7 @@ sub start_defaultvalue { sub end_defaultvalue { return ''; } +# Validators may need to take language specifications sub start_validator { my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_; @@ -926,7 +932,9 @@ package Apache::lonhelper::message; =pod -=head1 Element: messageX +=head1 Elements + +=head2 Element: messageX Message elements display their contents, and transition directly to the state in the attribute. Example: @@ -950,11 +958,17 @@ within each other.) This is also a good template for creating your own new states, as it has very little code beyond the state template. +=head3 Localization + +The contents of the message tag will be run through the +normalize_string function and that will be used as a call to &mt. + =cut no strict; @ISA = ("Apache::lonhelper::element"); use strict; +use Apache::lonlocal; BEGIN { &Apache::lonhelper::register('Apache::lonhelper::message', @@ -974,8 +988,8 @@ sub start_message { return ''; } - $paramHash->{MESSAGE_TEXT} = &Apache::lonxml::get_all_text('/message', - $parser); + $paramHash->{MESSAGE_TEXT} = &mtn(&Apache::lonxml::get_all_text('/message', + $parser)); if (defined($token->[2]{'nextstate'})) { $paramHash->{NEXTSTATE} = $token->[2]{'nextstate'}; @@ -996,7 +1010,7 @@ sub end_message { sub render { my $self = shift; - return $self->{MESSAGE_TEXT}; + return &mtn($self->{MESSAGE_TEXT}); } # If a NEXTSTATE was given, switch to it sub postprocess { @@ -1098,6 +1112,8 @@ tag is stored in the {VARS} hash. no strict; @ISA = ("Apache::lonhelper::element"); use strict; +use Apache::lonlocal; +use Apache::lonnet; BEGIN { &Apache::lonhelper::register('Apache::lonhelper::choices', @@ -1144,11 +1160,11 @@ sub start_choice { } my $computer = $token->[2]{'computer'}; - my $human = &Apache::lonxml::get_all_text('/choice', - $parser); + my $human = &mt(&Apache::lonxml::get_all_text('/choice', + $parser)); my $nextstate = $token->[2]{'nextstate'}; my $evalFlag = $token->[2]{'eval'}; - push @{$paramHash->{CHOICES}}, [$human, $computer, $nextstate, + push @{$paramHash->{CHOICES}}, [&mtn($human), $computer, $nextstate, $evalFlag]; return ''; } @@ -1157,6 +1173,13 @@ sub end_choice { return ''; } +{ + # used to generate unique id attributes for tags. + # internal use only. + my $id = 0; + sub new_id { return $id++; } +} + sub render { my $self = shift; my $var = $self->{'variable'}; @@ -1165,7 +1188,8 @@ sub render { if ($self->{'multichoice'}) { $result .= < + SCRIPT } @@ -1181,10 +1206,13 @@ SCRIPT # Only print "select all" and "unselect all" if there are five or # more choices; fewer then that and it looks silly. if ($self->{'multichoice'} && scalar(@{$self->{CHOICES}}) > 4) { + my %lt=&Apache::lonlocal::texthash( + 'sa' => "Select All", + 'ua' => "Unselect All"); $buttons = < - - + +
  BUTTONS } @@ -1236,14 +1264,16 @@ BUTTONS my $type = "radio"; if ($self->{'multichoice'}) { $type = 'checkbox'; } foreach my $choice (@{$self->{CHOICES}}) { + my $id = &new_id(); $result .= "\n \n"; $result .= "[1],"<>&\"'") . "'"; if ($checkedChoices{$choice->[1]}) { - $result .= " checked "; + $result .= " checked='checked' "; } + $result .= qq{id="id$id"}; my $choiceLabel = $choice->[0]; if ($choice->[4]) { # if we need to evaluate this choice $choiceLabel = "sub { my $helper = shift; my $state = shift;" . @@ -1251,7 +1281,8 @@ BUTTONS $choiceLabel = eval($choiceLabel); $choiceLabel = &$choiceLabel($helper, $self); } - $result .= "/> " . $choiceLabel . "\n"; + $result .= "/> ".qq{\n"; } $result .= "\n\n\n"; $result .= $buttons; @@ -1263,11 +1294,11 @@ BUTTONS # given, switch to it sub postprocess { my $self = shift; - my $chosenValue = $ENV{'form.' . $self->{'variable'} . '.forminput'}; + my $chosenValue = $env{'form.' . $self->{'variable'} . '.forminput'}; if (!defined($chosenValue) && !$self->{'allowempty'}) { - $self->{ERROR_MSG} = "You must choose one or more choices to" . - " continue."; + $self->{ERROR_MSG} = + &mt("You must choose one or more choices to continue."); return 0; } @@ -1310,9 +1341,14 @@ the result is stored in. =cut +# This really ought to be a sibling class to "choice" which is itself +# a child of some abstract class.... *shrug* + no strict; @ISA = ("Apache::lonhelper::element"); use strict; +use Apache::lonlocal; +use Apache::lonnet; BEGIN { &Apache::lonhelper::register('Apache::lonhelper::dropdown', @@ -1390,10 +1426,10 @@ sub render { $result .= "\n"; @@ -1413,7 +1449,7 @@ sub render { # given, switch to it sub postprocess { my $self = shift; - my $chosenValue = $ENV{'form.' . $self->{'variable'} . '.forminput'}; + my $chosenValue = $env{'form.' . $self->{'variable'} . '.forminput'}; if (!defined($chosenValue) && !$self->{'allowempty'}) { $self->{ERROR_MSG} = "You must choose one or more choices to" . @@ -1471,7 +1507,8 @@ Example: no strict; @ISA = ("Apache::lonhelper::element"); use strict; - +use Apache::lonlocal; # A localization nightmare +use Apache::lonnet; use Time::localtime; BEGIN { @@ -1499,6 +1536,7 @@ sub start_date { $paramHash->{'variable'} = $token->[2]{'variable'}; $helper->declareVar($paramHash->{'variable'}); $paramHash->{'hoursminutes'} = $token->[2]{'hoursminutes'}; + $paramHash->{'anytime'} = $token->[2]{'anytime'}; } sub end_date { @@ -1517,9 +1555,22 @@ sub render { my $var = $self->{'variable'}; my $date; - + + my $time=time; + my ($anytime,$onclick); + + if (defined($self->{DEFAULT_VALUE})) { + my $valueFunc = eval($self->{DEFAULT_VALUE}); + die('Error in default value code for variable ' . + $self->{'variable'} . ', Perl said: ' . $@) if $@; + $time = &$valueFunc($helper, $self); + if (lc($time) eq 'anytime') { $time=time; $anytime=1; } + } + if ($anytime) { + $onclick = "onclick=\"javascript:updateCheck(this.form,'${var}anytime',false)\""; + } # Default date: The current hour. - $date = localtime(); + $date = localtime($time); $date->min(0); if (defined $self->{ERROR_MSG}) { @@ -1528,22 +1579,22 @@ sub render { # Month my $i; - $result .= "\n"; for ($i = 0; $i < 12; $i++) { if ($i == $date->mon) { - $result .= "\n"; + $result .= &mt($months[$i]) . "\n"; } $result .= "\n"; # Day - $result .= "\n"; for ($i = 1; $i < 32; $i++) { if ($i == $date->mday) { - $result .= '\n"; for ($i = 1; $i < 12; $i++) { if ($date->hour == $i) { - $result .= "\n"; + $result .= "\n"; } else { - $result .= "\n"; + $result .= "\n"; } } - $result .= "\n"; + $result .= "\n"; for ($i = 13; $i < 24; $i++) { my $printedHour = $i - 12; if ($date->hour == $i) { - $result .= "\n"; + $result .= "\n"; } else { - $result .= "\n"; + $result .= "\n"; } } $result .= " :\n"; - $result .= "\n"; + my $selected=0; + for my $i ((0,15,30,45,59,undef,0..59)) { my $printedMinute = $i; - if ($i < 10) { + if (defined($i) && $i < 10) { $printedMinute = "0" . $printedMinute; } - if ($date->min == $i) { - $result .= "