--- loncom/interface/lonhtmlcommon.pm 2002/07/22 20:35:05 1.1
+++ loncom/interface/lonhtmlcommon.pm 2016/01/26 14:30:25 1.370
@@ -1,246 +1,3965 @@
+# The LearningOnline Network with CAPA
+# a pile of common html routines
+#
+# $Id: lonhtmlcommon.pm,v 1.370 2016/01/26 14:30:25 raeburn Exp $
+#
+# Copyright Michigan State University Board of Trustees
+#
+# This file is part of the LearningOnline Network with CAPA (LON-CAPA).
+#
+# LON-CAPA is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# LON-CAPA is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with LON-CAPA; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+# /home/httpd/html/adm/gpl.txt
+#
+# http://www.lon-capa.org/
+#
+######################################################################
+######################################################################
+
+=pod
+
+=head1 NAME
+
+Apache::lonhtmlcommon - routines to do common html things
+
+=head1 SYNOPSIS
+
+Referenced by other mod_perl Apache modules.
+
+=head1 INTRODUCTION
+
+lonhtmlcommon is a collection of subroutines used to present information
+in a consistent html format, or provide other functionality related to
+html.
+
+=head2 General Subroutines
+
+=over 4
+
+=cut
+
+######################################################################
+######################################################################
+
package Apache::lonhtmlcommon;
use strict;
+use Time::Local;
+use Time::HiRes;
+use Apache::lonlocal;
+use Apache::lonnet;
+use HTML::Entities();
+use LONCAPA qw(:DEFAULT :match);
+
+sub java_not_enabled {
+ if (($env{'browser.mobile'}) && ($env{'browser.mobile'} =~ /^ipad|ipod|iphone$/i)) {
+ return "\n".''.
+ &mt('The required Java applet could not be started, because Java is not supported by your mobile device.').
+ "\n";
+ } else {
+ return "\n".''.
+ &mt('The required Java applet could not be started. Please make sure to have Java installed and active in your browser.').
+ "\n";
+ }
+}
-sub MapOptions {
- my ($data, $page)=@_;
- my $Str = '';
- $Str .= ''."\n";
+=item &confirm_success()
+
+Successful completion of an operation message
+
+=cut
+
+sub confirm_success {
+ my ($message,$failure)=@_;
+ if ($failure) {
+ return ''."\n"
+ .' '."\n"
+ .$message."\n"
+ .''."\n";
+ } else {
+ return ''."\n"
+ .' '."\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',undef,undef,undef,undef,'mathhelpicon_'.$textarea);
+ }
+ 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 &dependencies_button()
+
+Creates a button that launches a popup-window, in which dependencies
+for the web page in the main window can be added to, replaced or deleted.
+
+=cut
+
+sub dependencies_button {
+ my $buttontext=&mt('Manage Dependencies');
+ return <<"END";
+
+END
+}
+
+##############################################
+
+=pod
+
+=item &dependencycheck_js()
+
+Javascript used to open pop-up window containing interface to manage
+dependencies for a web page uploaded diretcly to a course.
+
+=cut
+
+sub dependencycheck_js {
+ my ($symb,$title,$url,$folderpath,$uri) = @_;
+ my $link;
+ if ($symb) {
+ $link = '/adm/dependencies?symb='.&HTML::Entities::encode($symb,'<>&"');
+ } elsif ($folderpath) {
+ $link = '/adm/dependencies?folderpath='.&HTML::Entities::encode($folderpath,'<>&"');
+ $url = $uri;
+ } elsif ($uri =~ m{^/public/$match_domain/$match_courseid/syllabus$}) {
+ $link = '/adm/dependencies';
+ }
+ $link .= (($link=~/\?/)?'&':'?').'title='.
+ &HTML::Entities::encode($title,'<>&"');
+ if ($url) {
+ $link .= '&url='.&HTML::Entities::encode($url,'<>&"');
+ }
+ return <
+ //
+
+ENDJS
+}
+
+##############################################
+##############################################
+
+=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 ''.
+ &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()
+
+=cut
+##############################################
+##############################################
+sub textbox {
+ my ($name,$value,$size,$special) = @_;
+ $size = 40 if (! defined($size));
+ $value = &HTML::Entities::encode($value,'<>&"');
+ my $Str = '';
return $Str;
}
-sub StudentOptions {
- my ($cache, $students, $selectedName, $page)=@_;
+##############################################
+##############################################
- my $Str = '';
- $Str = ''."\n";
+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;
+}
+
+
+##############################################
+##############################################
+=pod
+
+=item &get_date_from_form()
+
+get_date_from_form retrieves the date specified in an &date_setter form.
+
+=over
+
+=item Inputs:
+
+=over 4
+
+=item $dname
+
+The name passed to &date_setter, which prefixes the form elements.
+
+=item $defaulttime
+
+The unix time to use as the default in case of poor inputs.
+
+=back
+
+=back
+
+Returns: Unix time represented in the form.
+
+=cut
+
+##############################################
+##############################################
+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 (($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 (($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 < 24)) {
+ $hour = $tmphour;
+ }
+ } else {
+ $hour = 0;
+ }
+ 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 (($tmpmonth =~ /^\d+$/) && ($tmpmonth > 0) && ($tmpmonth < 13)) {
+ $month = $tmpmonth;
+ }
+ }
+ if (defined($env{'form.'.$dname.'_year'})) {
+ my $tmpyear = $env{'form.'.$dname.'_year'};
+ if (($tmpyear =~ /^\d+$/) && ($tmpyear >= 1970)) {
+ $year = $tmpyear;
+ }
+ }
+ 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;
+ }
+}
+
+##############################################
+##############################################
+
+=pod
+
+=item &pjump_javascript_definition()
+
+Returns javascript defining the 'pjump' function, which opens up a
+parameter setting wizard.
+
+=cut
+
+##############################################
+##############################################
+sub pjump_javascript_definition {
+ my $Str = <Active'."\n";
- $Str .= ''."\n";
- $Str .= ''."\n";
+ 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 .= '