--- loncom/interface/lonhtmlcommon.pm 2003/10/14 18:36:54 1.31 +++ loncom/interface/lonhtmlcommon.pm 2009/12/07 17:30:01 1.253.2.1 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # a pile of common html routines # -# $Id: lonhtmlcommon.pm,v 1.31 2003/10/14 18:36:54 www Exp $ +# $Id: lonhtmlcommon.pm,v 1.253.2.1 2009/12/07 17:30:01 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -55,14 +55,247 @@ html. package Apache::lonhtmlcommon; +use strict; use Time::Local; +use Time::HiRes; use Apache::lonlocal; -use strict; +use Apache::lonnet; +use LONCAPA; + + +sub coursepreflink { + my ($text,$category)=@_; + if (&Apache::lonnet::allowed('opa',$env{'request.course.id'})) { + return ''.$text.''; + } else { + return ''; + } +} + +sub raw_href_to_link { + my ($message)=@_; + $message=~s/(https?\:\/\/[^\s\'\"]+)(\s|$)/$1<\/tt><\/a>$2/gi; + return $message; +} + +############################################## +############################################## + +=pod + +=item confirm_success + +Successful completion of an operation message + +=cut + +sub confirm_success { + my ($message,$failure)=@_; + if ($failure) { + return ''."\n" + .''.&mt('Error').' '."\n" + .$message."\n" + .''."\n"; + } else { + return ''."\n" + .''.&mt('OK').' '."\n" + .$message."\n" + .''."\n"; + } +} + +############################################## +############################################## + +=pod + +=item dragmath_button + +Creates a button that launches a dragmath popup-window, in which an +expression can be edited and pasted as LaTeX into a specified textarea. + + textarea - Name of the textarea to edit. + helpicon - If true, show a help icon to the right of the button. + +=cut + +sub dragmath_button { + my ($textarea,$helpicon) = @_; + my $help_text; + if ($helpicon) { + $help_text = &Apache::loncommon::help_open_topic('Authoring_Math_Editor'); + } + my $buttontext=&mt('Edit Math'); + return <$help_text +ENDDRAGMATH +} + +############################################## + +=pod + +=item dragmath_js + +Javascript used to open pop-up window containing dragmath applet which +can be used to paste LaTeX into a textarea. + +=cut + +sub dragmath_js { + my ($popup) = @_; + return < + // + +ENDDRAGMATHJS +} + + +############################################## +############################################## + +=pod + +=item authorbombs + +=cut ############################################## ############################################## +sub authorbombs { + my $url=shift; + $url=&Apache::lonnet::declutter($url); + my ($udom,$uname)=($url=~m{^($LONCAPA::domain_re)/($LONCAPA::username_re)/}); + my %bombs=&Apache::lonmsg::all_url_author_res_msg($uname,$udom); + foreach my $bomb (keys(%bombs)) { + if ($bomb =~ /^$udom\/$uname\//) { + return ''.&mt('Bomb').''. + &Apache::loncommon::help_open_topic('About_Bombs'); + } + } + return ''; +} + +############################################## +############################################## + +sub recent_filename { + my $area=shift; + return 'nohist_recent_'.&escape($area); +} + +sub store_recent { + my ($area,$name,$value,$freeze)=@_; + my $file=&recent_filename($area); + my %recent=&Apache::lonnet::dump($file); + if (scalar(keys(%recent))>20) { +# remove oldest value + my $oldest=time(); + my $delkey=''; + foreach my $item (keys(%recent)) { + my $thistime=(split(/\&/,$recent{$item}))[0]; + if (($thistime ne "always_include") && ($thistime<$oldest)) { + $oldest=$thistime; + $delkey=$item; + } + } + &Apache::lonnet::del($file,[$delkey]); + } +# store new value + my $timestamp; + if ($freeze) { + $timestamp = "always_include"; + } else { + $timestamp = time(); + } + &Apache::lonnet::put($file,{ $name => + $timestamp.'&'.&escape($value) }); +} + +sub remove_recent { + my ($area,$names)=@_; + my $file=&recent_filename($area); + return &Apache::lonnet::del($file,$names); +} + +sub select_recent { + my ($area,$fieldname,$event)=@_; + my %recent=&Apache::lonnet::dump(&recent_filename($area)); + my $return="\n\n"; + return $return; +} + +sub get_recent { + my ($area, $n) = @_; + my %recent=&Apache::lonnet::dump(&recent_filename($area)); + +# Create hash with key as time and recent as value +# Begin filling return_hash with any 'always_include' option + my %time_hash = (); + my %return_hash = (); + foreach my $item (keys(%recent)) { + my ($thistime,$thisvalue)=(split(/\&/,$recent{$item})); + if ($thistime eq 'always_include') { + $return_hash{$item} = &unescape($thisvalue); + $n--; + } else { + $time_hash{$thistime} = $item; + } + } + +# Sort by decreasing time and return key value pairs + my $idx = 1; + foreach my $item (reverse(sort(keys(%time_hash)))) { + $return_hash{$time_hash{$item}} = + &unescape((split(/\&/,$recent{$time_hash{$item}}))[1]); + if ($n && ($idx++ >= $n)) {last;} + } + + return %return_hash; +} + +sub get_recent_frozen { + my ($area) = @_; + my %recent=&Apache::lonnet::dump(&recent_filename($area)); + +# Create hash with all 'frozen' items + my %return_hash = (); + foreach my $item (keys(%recent)) { + my ($thistime,$thisvalue)=(split(/\&/,$recent{$item})); + if ($thistime eq 'always_include') { + $return_hash{$item} = &unescape($thisvalue); + } + } + return %return_hash; +} + + + =pod =item textbox @@ -74,6 +307,7 @@ use strict; sub textbox { my ($name,$value,$size,$special) = @_; $size = 40 if (! defined($size)); + $value = &HTML::Entities::encode($value,'<>&"'); my $Str = ''; return $Str; @@ -91,12 +325,39 @@ sub textbox { ############################################## ############################################## sub checkbox { - my ($name) = @_; - my $Str = ''; + my ($name,$checked,$value) = @_; + my $Str = ' + ENDJS - $result .= " }; + # Month my @Months = qw/January February March April May June July August September October November December/; # Pad @Months with a bogus value to make indexing easier unshift(@Months,'If you can read this an error occurred'); + if ($includeempty) { $monthselector.=""; } for(my $m = 1;$m <=$#Months;$m++) { - $result .= " \n\n"; + $timest=&mt($timest); + $hourselector .= $timest." \n"; + } + $hourselector .= " \n"; + my $minuteselector = qq{}; + my $secondselector= qq{}; + my $cal_link; + if (!$nolink) { + $cal_link = qq{}; + } + # + my $tzone = ' '.$tzname.' '; + if ($no_hh_mm_ss) { + $result .= &mt('[_1] [_2] [_3] ', + $monthselector,$dayselector,$yearselector). + $tzone; + if (!$nolink) { + $result .= &mt('[_1]Select Date[_2]',$cal_link,''); + } + } else { + $result .= &mt('[_1] [_2] [_3] [_4] [_5]m [_6]s ', + $monthselector,$dayselector,$yearselector, + $hourselector,$minuteselector,$secondselector). + $tzone; + if (!$nolink) { + $result .= &mt('[_1]Select Date[_2]',$cal_link,''); + } + } + $result .= "\n\n"; return $result; } +sub get_timedates { + my ($epoch) = @_; + my $dt = DateTime->from_epoch(epoch => $epoch) + ->set_time_zone(&Apache::lonlocal::gettimezone()); + my $tzname = $dt->time_zone_short_name(); + my $sec = $dt->second; + my $min = $dt->minute; + my $hour = $dt->hour; + my $mday = $dt->day; + my $month = $dt->month; + if ($month) { + $month --; + } + my $year = $dt->year; + return ($tzname,$sec,$min,$hour,$mday,$month,$year); +} + +sub build_url { + my ($base, $fields)=@_; + my $url; + $url = $base.'?'; + foreach my $key (keys(%$fields)) { + $url.=&escape($key).'='.&escape($$fields{$key}).'&'; + } + $url =~ s/&$//; + return $url; +} + + ############################################## ############################################## @@ -256,7 +628,7 @@ Inputs: =item $dname -The name passed to &datesetter, which prefixes the form elements. +The name passed to &date_setter, which prefixes the form elements. =item $defaulttime @@ -274,45 +646,68 @@ sub get_date_from_form { my ($dname) = @_; my ($sec,$min,$hour,$day,$month,$year); # - if (defined($ENV{'form.'.$dname.'_second'})) { - my $tmpsec = $ENV{'form.'.$dname.'_second'}; + if (defined($env{'form.'.$dname.'_second'})) { + my $tmpsec = $env{'form.'.$dname.'_second'}; if (($tmpsec =~ /^\d+$/) && ($tmpsec >= 0) && ($tmpsec < 60)) { $sec = $tmpsec; } + if (!defined($tmpsec) || $tmpsec eq '') { $sec = 0; } + } else { + $sec = 0; } - if (defined($ENV{'form.'.$dname.'_minute'})) { - my $tmpmin = $ENV{'form.'.$dname.'_minute'}; + if (defined($env{'form.'.$dname.'_minute'})) { + my $tmpmin = $env{'form.'.$dname.'_minute'}; if (($tmpmin =~ /^\d+$/) && ($tmpmin >= 0) && ($tmpmin < 60)) { $min = $tmpmin; } + if (!defined($tmpmin) || $tmpmin eq '') { $min = 0; } + } else { + $min = 0; } - if (defined($ENV{'form.'.$dname.'_hour'})) { - my $tmphour = $ENV{'form.'.$dname.'_hour'}; - if (($tmphour =~ /^\d+$/) && ($tmphour > 0) && ($tmphour < 32)) { + if (defined($env{'form.'.$dname.'_hour'})) { + my $tmphour = $env{'form.'.$dname.'_hour'}; + if (($tmphour =~ /^\d+$/) && ($tmphour >= 0) && ($tmphour < 24)) { $hour = $tmphour; } + } else { + $hour = 0; } - if (defined($ENV{'form.'.$dname.'_day'})) { - my $tmpday = $ENV{'form.'.$dname.'_day'}; + if (defined($env{'form.'.$dname.'_day'})) { + my $tmpday = $env{'form.'.$dname.'_day'}; if (($tmpday =~ /^\d+$/) && ($tmpday > 0) && ($tmpday < 32)) { $day = $tmpday; } } - if (defined($ENV{'form.'.$dname.'_month'})) { - my $tmpmonth = $ENV{'form.'.$dname.'_month'}; + if (defined($env{'form.'.$dname.'_month'})) { + my $tmpmonth = $env{'form.'.$dname.'_month'}; if (($tmpmonth =~ /^\d+$/) && ($tmpmonth > 0) && ($tmpmonth < 13)) { - $month = $tmpmonth - 1; + $month = $tmpmonth; } } - if (defined($ENV{'form.'.$dname.'_year'})) { - my $tmpyear = $ENV{'form.'.$dname.'_year'}; - if (($tmpyear =~ /^\d+$/) && ($tmpyear > 1900)) { - $year = $tmpyear - 1900; + if (defined($env{'form.'.$dname.'_year'})) { + my $tmpyear = $env{'form.'.$dname.'_year'}; + if (($tmpyear =~ /^\d+$/) && ($tmpyear >= 1970)) { + $year = $tmpyear; } } - if (($year<70) || ($year>137)) { return undef; } - if (eval(&timelocal($sec,$min,$hour,$day,$month,$year))) { - return &timelocal($sec,$min,$hour,$day,$month,$year); + if (($year<1970) || ($year>2037)) { return undef; } + if (defined($sec) && defined($min) && defined($hour) && + defined($day) && defined($month) && defined($year)) { + my $timezone = &Apache::lonlocal::gettimezone(); + my $dt = DateTime->new( year => $year, + month => $month, + day => $day, + hour => $hour, + minute => $min, + second => $sec, + time_zone => $timezone, + ); + my $epoch_time = $dt->epoch; + if ($epoch_time ne '') { + return $epoch_time; + } else { + return undef; + } } else { return undef; } @@ -334,11 +729,13 @@ parameter setting wizard. ############################################## sub pjump_javascript_definition { my $Str = <'. - 'Currently Enrolled'."\n"; - $Str .= ''."\n"; - $Str .= ''."\n"; - $Str .= ''."\n"; -} - - -######################################################## -######################################################## - -=pod - -=item &MultipleSectionSelect() - -Inputs: - -=over 4 - -=item $sections A references to an array containing the names of all the -sections used in a class. - -=item $selectedSections A reference to an array containing the names of the -currently selected sections. - -=back - -Returns: a string containing HTML for a multiple select box for -selecting sections of a course. - -The form element name is 'Section'. @$sections is sorted prior to output. - -=cut - -######################################################## -######################################################## -sub MultipleSectionSelect { - my ($sections,$selectedSections)=@_; - - my $Str = ''; - $Str .= ''."\n"; - - return $Str; -} - -######################################################## -######################################################## - -=pod - -=item &Title() - -Inputs: $pageName a string containing the name of the page to be sent -to &Apache::loncommon::bodytag. - -Returns: string containing being and complete and -as well as a <script> to focus the current window and change its width -and height to 500. Why? I do not know. If you find out, please update -this documentation. - -=cut - -######################################################## -######################################################## -sub Title { - my ($pageName)=@_; - - my $Str = ''; - - $Str .= '<html><head><title>'.$pageName.''."\n"; - $Str .= &Apache::loncommon::bodytag($pageName)."\n"; - $Str .= ''."\n"; - - return $Str; -} - -######################################################## -######################################################## - -=pod - -=item &CreateHeadings() - -This function generates the column headings for the chart. - -=over 4 - -Inputs: $CacheData, $keyID, $headings, $spacePadding - -$CacheData: pointer to a hash tied to the cached data database - -$keyID: a pointer to an array containing the names of the data -held in a column and is used as part of a key into $CacheData - -$headings: The names of the headings for the student information - -$spacePadding: The spaces to go between columns - -Output: $Str - -$Str: A formatted string of the table column headings. - -=back - -=cut - -######################################################## -######################################################## -sub CreateHeadings { - my ($data,$keyID,$headings,$displayString,$format)=@_; - my $Str=''; - my $formatting = ''; - - for(my $index=0; $index<(scalar @$headings); $index++) { - my $currentHeading=$headings->[$index]; - if($format eq 'preformatted') { - my @dataLength=split(//,$currentHeading); - my $length=scalar @dataLength; - $formatting = (' 'x - ($data->{$keyID->[$index].':columnWidth'}-$length)); - } - my $linkdata=$keyID->[$index]; - - my $tempString = $displayString; - $tempString =~ s/LINKDATA/$linkdata/; - $tempString =~ s/DISPLAYDATA/$currentHeading/; - $tempString =~ s/FORMATTING/$formatting/; - - $Str .= $tempString; + foreach my $type (['Active', &mt('Currently Has Access')], + ['Future', &mt('Will Have Future Access')], + ['Expired', &mt('Previously Had Access')], + ['Any', &mt('Any Access Status')]) { + my ($name,$label) = @$type; + $Str .= '