--- loncom/interface/lonhtmlcommon.pm 2016/10/31 21:00:49 1.358.2.9
+++ loncom/interface/lonhtmlcommon.pm 2018/12/27 20:10:31 1.394
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# a pile of common html routines
#
-# $Id: lonhtmlcommon.pm,v 1.358.2.9 2016/10/31 21:00:49 raeburn Exp $
+# $Id: lonhtmlcommon.pm,v 1.394 2018/12/27 20:10:31 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -78,7 +78,11 @@ sub java_not_enabled {
sub coursepreflink {
my ($text,$category)=@_;
if (&Apache::lonnet::allowed('opa',$env{'request.course.id'})) {
- return '&"').'">'.$text.'';
+ my $target =' target="_top"';
+ if (($env{'request.lti.login'}) && ($env{'request.lti.target'} eq 'iframe')) {
+ $target ='';
+ }
+ return '&"').'">'.$text.'';
} else {
return '';
}
@@ -92,7 +96,7 @@ sub raw_href_to_link {
sub entity_encode {
my ($text)=@_;
- return &HTML::Entities::encode($text, '<>&"');
+ return &HTML::Entities::encode($text, '\'<>&"');
}
sub direct_parm_link {
@@ -101,9 +105,13 @@ sub direct_parm_link {
$filter=&entity_encode($filter);
$part=&entity_encode($part);
if (($symb) && (&Apache::lonnet::allowed('opa')) && ($target ne 'tex')) {
- return "$linktext";
+ my $target=' target="_top"';
+ if (($env{'request.lti.login'}) && ($env{'request.lti.target'} eq 'iframe')) {
+ $target='';
+ }
+ return "$linktext";
} else {
- return $linktext;
+ return $linktext;
}
}
##############################################
@@ -407,7 +415,7 @@ sub textbox {
##############################################
##############################################
sub checkbox {
- my ($name,$checked,$value) = @_;
+ my ($name,$checked,$value,$special) = @_;
my $Str = '';
return $Str;
}
@@ -451,10 +459,12 @@ sub radio {
&date_setter returns html and javascript for a compact date-setting form.
To retrieve values from it, use &get_date_from_form.
-Inputs
-
=over 4
+=item Inputs
+
+=over
+
=item $dname
The name to prepend to the form elements.
@@ -515,10 +525,12 @@ If true, text boxes for seconds are omit
=back
-Bugs
+=item Bugs
The method used to restrict user input will fail in the year 2400.
+=back
+
=cut
##############################################
@@ -671,7 +683,7 @@ ENDJS
my $minuteselector = qq{};
my $secondselector= qq{};
my $cal_link;
- if (!$nolink) {
+ unless (($nolink) || ($state eq 'disabled')) {
$cal_link = qq{};
}
#
@@ -685,18 +697,20 @@ ENDJS
$monthselector,$dayselector,$yearselector,
$hourselector).
$tzone;
+
} elsif ($no_ss) {
$result .= &mt('[_1] [_2] [_3] [_4] [_5]m',
$monthselector,$dayselector,$yearselector,
$hourselector,$minuteselector).
$tzone;
+
} else {
$result .= &mt('[_1] [_2] [_3] [_4] [_5]m [_6]s ',
$monthselector,$dayselector,$yearselector,
$hourselector,$minuteselector,$secondselector).
$tzone;
}
- if (!$nolink) {
+ unless (($nolink) || ($state eq 'disabled')) {
$result .= &mt('[_1]Select Date[_2]',$cal_link,'');
}
$result .= "\n\n";
@@ -741,7 +755,9 @@ sub build_url {
get_date_from_form retrieves the date specified in an &date_setter form.
-Inputs:
+=over
+
+=item Inputs:
=over 4
@@ -755,6 +771,8 @@ The unix time to use as the default in c
=back
+=back
+
Returns: Unix time represented in the form.
=cut
@@ -926,7 +944,9 @@ sub javascript_docopen {
Returns html for a selection box which allows the user to choose the
enrollment status of students. The selection box name is 'Status'.
-Inputs:
+=over
+
+=item Inputs:
$status: the currently selected status. If undefined the value of
$env{'form.Status'} is taken. If that is undefined, a value of 'Active'
@@ -940,6 +960,8 @@ $size: the size (number of lines) of the
$onchange: javascript to use when the value is changed. Enclosed in
double quotes, ""s, not single quotes.
+=back
+
Returns: a perl string as described.
=cut
@@ -987,7 +1009,7 @@ sub StatusOptions {
=pod
-=item Progess Window Handling Routines
+=item Progress Window Handling Routines
These routines handle the creation, update, increment, and closure of
progress windows. The progress window reports to the user the number
@@ -1001,25 +1023,34 @@ of items completed and an estimate of th
Writes javascript to the client to open a progress window and returns a
data structure used for bookkeeping.
-Inputs
+=over
-=over 4
+=item Inputs
+
+=over
=item $r Apache request
=item $number_to_do The total number of items being processed.
+=item $preamble Optional HTML to display before the progress bar.
+
=back
-Returns a hash containing the progress state data structure.
+=back
+Returns a hash containing the progress state data structure.
+If $number_to_do is zero or null, an indeterminate progress bar will
+be used.
=item &Update_PrgWin()
Updates the text in the progress indicator. Does not increment the count.
See &Increment_PrgWin.
-Inputs:
+=over
+
+=item Inputs:
=over 4
@@ -1031,25 +1062,38 @@ Inputs:
=back
+=back
+
Returns: none
-=item Increment_PrgWin()
+=item &Increment_PrgWin()
Increment the count of items completed for the progress window by $step or 1 if no step is provided.
-Inputs:
+=over
+
+=item Inputs:
=over 4
-=item $r Apache request
+=item $r
-=item $prog_state Pointer to the data structure returned by Create_PrgWin
+Apache request
+
+=item $prog_state
+
+Pointer to the data structure returned by Create_PrgWin
+
+=item $extraInfo
-=item $extraInfo A description of the items being iterated over. Typically
-'student'.
+A description of the items being iterated over. Typically 'student'.
-=item $step (optional) counter step. Will be set to default 1 if ommited. step must be greater than 0 or empty.
+=item $step
+
+(optional) counter step. Will be set to default 1 if ommited. step must be greater than 0 or empty.
+
+=back
=back
@@ -1060,7 +1104,9 @@ Returns: none
Closes the progress window.
-Inputs:
+=over
+
+=item Inputs:
=over 4
@@ -1070,6 +1116,8 @@ Inputs:
=back
+=back
+
Returns: none
=back
@@ -1082,20 +1130,20 @@ Returns: none
# Create progress
sub Create_PrgWin {
- my ($r,$number_to_do)=@_;
+ my ($r,$number_to_do,$preamble)=@_;
my %prog_state;
$prog_state{'done'}=0;
$prog_state{'firststart'}=&Time::HiRes::time();
$prog_state{'laststart'}=&Time::HiRes::time();
$prog_state{'max'}=$number_to_do;
- &Apache::loncommon::LCprogressbar($r);
+ &Apache::loncommon::LCprogressbar($r,$prog_state{'max'},$preamble);
return %prog_state;
}
# update progress
sub Update_PrgWin {
my ($r,$prog_state,$displayString)=@_;
- &Apache::loncommon::LCprogressbarUpdate($r,undef,$displayString);
+ &Apache::loncommon::LCprogressbarUpdate($r,undef,$displayString,$$prog_state{'max'});
$$prog_state{'laststart'}=&Time::HiRes::time();
}
@@ -1145,7 +1193,7 @@ sub Increment_PrgWin {
if ($$prog_state{'max'}) {
$percent=int(100.*$current/$$prog_state{'max'});
}
- &Apache::loncommon::LCprogressbarUpdate($r,$percent,$timeinfo);
+ &Apache::loncommon::LCprogressbarUpdate($r,$percent,$timeinfo,$$prog_state{'max'});
$$prog_state{'laststart'}=&Time::HiRes::time();
}
@@ -1162,7 +1210,7 @@ sub Close_PrgWin {
sub crumbs {
my ($uri,$target,$prefix,$form,$skiplast,$onclick)=@_;
# You cannot crumbnify uploaded or adm resources
- if ($uri=~/^\/*(uploaded|adm)\//) { return &mt('(Internal Course/Group Content)'); }
+ if ($uri=~/^\/*(uploaded|adm)\//) { return &mt('(Internal Course/Community Content)'); }
if ($target) {
$target = ' target="'.
&Apache::loncommon::escape_single($target).'"';
@@ -1182,6 +1230,12 @@ sub crumbs {
} else {
$path.='/';
}
+ if ($path eq '/res/') {
+ unless (&Apache::lonnet::allowed('bre',$path)) {
+ $output.="$dir/";
+ next;
+ }
+ }
my $href_path = &HTML::Entities::encode($path,'<>&"');
&Apache::loncommon::inhibit_menu_check(\$href_path);
if ($form) {
@@ -1259,9 +1313,9 @@ sub htmlareaheaders {
ENDEDITOR
}
$s.=(<
-
-
+
+
+
@@ -1298,6 +1352,68 @@ $(document).ready(function(){
});';
}
+sub countdown {
+
+ # Code to put a due date countdown in 'duedatecountdown' span.
+ # This is currently located in the breadcrumb headers.
+ # note that the dueDateLayout is internatinoalized below.
+ # Here document is used to support the substitution into the javascript below.
+ # ..which unforunately necessitates escaping the $'s in the javascript.
+ # There are several times of importance
+ #
+ # serverDueDate - The absolute time at which the problem expires.
+ # serverTime - The server's time when the problem finished computing.
+ # clientTime - The client's time...as close to serverTime as possible.
+ # The clientTime will be slightly later due to
+ # 1. The latency between problem computation and
+ # the first network action.
+ # 2. The time required between the page load-start and the actual
+ # initial javascript execution that got clientTime.
+ # These are used as follows:
+ # The difference between clientTime and serverTime are used to
+ # correct for differences in clock settings between the browser's system and the
+ # server's.
+ #
+ # The difference between clientTime and the time at which the ready() method
+ # starts executing is used to estimate latencies for page load and submission.
+ # Since this is an estimate, it is doubled. The latency estimate + one minute
+ # is used to determine when the countdown timer turns red to warn the user
+ # to think about submitting.
+
+
+ my $dueDateLayout = &mt('Due in: {dn} {dl} {hnn}{sep}{mnn}{sep}{snn} [_1]',
+ "");
+ my $early = '- '.&mt('Submit Early').'';
+ my $pastdue = '- '.&mt('Past Due').'';
+ return <<"JAVASCRIPT";
+
+ var documentReadyTime;
+
+\$(document).ready(function() {
+ if (typeof(dueDate) != "undefined") {
+ documentReadyTime = (new Date()).getTime();
+ \$("#duedatecountdown").countdown({until: dueDate, compact: true,
+ layout: "$dueDateLayout",
+ onTick: function (periods) {
+ var latencyEstimate = (documentReadyTime - clientTime) * 2;
+ if(\$.countdown.periodsToSeconds(periods) < (300 + latencyEstimate)) {
+ \$("#submitearly").html("$early");
+ if (\$.countdown.periodsToSeconds(periods) < 1) {
+ \$("#submitearly").html("$pastdue");
+ }
+ }
+ if(\$.countdown.periodsToSeconds(periods) < (60 + latencyEstimate)) {
+ \$(this).css("color", "red"); //Highlight last minute.
+ }
+ }
+ });
+ }
+});
+
+JAVASCRIPT
+
+}
+
# ----------------------------------------- Script to activate only some fields
sub htmlareaselectactive {
@@ -1521,62 +1637,11 @@ sub htmlareaselectactive {
});
';
- $output .= &color_picker;
-
- # Code to put a due date countdown in 'duedatecountdown' span.
- # This is currently located in the breadcrumb headers.
- # note that the dueDateLayout is internatinoalized below.
- # Here document is used to support the substitution into the javascript below.
- # ..which unforunately necessitates escaping the $'s in the javascript.
- # There are several times of importance
- #
- # serverDueDate - The absolute time at which the problem expires.
- # serverTime - The server's time when the problem finished computing.
- # clientTime - The client's time...as close to serverTime as possible.
- # The clientTime will be slightly later due to
- # 1. The latency between problem computation and
- # the first network action.
- # 2. The time required between the page load-start and the actual
- # initial javascript execution that got clientTime.
- # These are used as follows:
- # The difference between clientTime and serverTime are used to
- # correct for differences in clock settings between the browser's system and the
- # server's.
- #
- # The difference between clientTime and the time at which the ready() method
- # starts executing is used to estimate latencies for page load and submission.
- # Since this is an estimate, it is doubled. The latency estimate + one minute
- # is used to determine when the countdown timer turns red to warn the user
- # to think about submitting.
+ $output .= &color_picker();
- my $dueDateLayout = &mt('Due in: {dn} {dl} {hnn}{sep}{mnn}{sep}{snn} [_1]',
- "");
- my $early = '- '.&mt('Submit Early').'';
- my $pastdue = '- '.&mt('Past Due').'';
- $output .= <'/adm/menu',
title =>'Go to main menu',
- target =>'_top',
+ target =>$target,
text =>$description,
no_mt =>$no_mt_descr, };
if($last) {
@@ -1853,7 +1958,10 @@ returns: nothing
class => 'LC_menubuttons_link',
};
if ($env{'request.noversionuri'} eq '/adm/searchcat') {
- $hashref->{'target'} = '_top';
+ $hashref->{'target'} = '_top';
+ if (($env{'request.lti.login'}) && ($env{'request.lti.target'} eq 'iframe')) {
+ $hashref->{'target'} = '';
+ }
}
$links=&htmltag( 'a','',
$hashref);
@@ -1977,7 +2085,9 @@ Adds $html to $category of the breadcrum
$html is usually a link to a page that invokes a function on the currently
displayed data (e.g. print when viewing a problem)
-Currently there are 3 possible values for $category:
+=over
+
+=item Currently there are 3 possible values for $category:
=over
@@ -1991,7 +2101,9 @@ remaining items in right of breadcrumbs
advanced tools shown in a separate box below breadcrumbs line
=back
-
+
+=back
+
returns: nothing
=cut
@@ -2040,8 +2152,17 @@ returns: a hash containing the current b
Creates html for breadcrumb tools (categories navigation and tools) and inserts
\$breadcrumbs at the correct position.
-input: \$breadcrumbs - a reference to the string containing prepared
-breadcrumbs.
+=over
+
+=item input:
+
+=over
+
+=item \$breadcrumbs - a reference to the string containing prepared breadcrumbs.
+
+=back
+
+=back
returns: nothing
@@ -2067,8 +2188,17 @@ returns: nothing
Creates html for advanced tools (category advtools) and inserts \$breadcrumbs
at the correct position.
-input: \$breadcrumbs - a reference to the string containing prepared
-breadcrumbs (after render_tools call).
+=over
+
+=item input:
+
+=over
+
+=item \$breadcrumbs - a reference to the string containing prepared breadcrumbs (after render_tools call).
+
+=back
+
+=back
returns: nothing
@@ -2101,11 +2231,11 @@ sub docs_breadcrumbs {
my $foldername=shift(@folders);
if ($folderpath) {$folderpath.='&';}
$folderpath.=$folder.'&'.$foldername;
- my $url;
+ my $url = $env{'request.use_absolute'};
if ($allowed) {
- $url = '/adm/coursedocs?folderpath=';
+ $url .= '/adm/coursedocs?folderpath=';
} else {
- $url = '/adm/supplemental?folderpath=';
+ $url .= '/adm/supplemental?folderpath=';
}
$url .= &escape($folderpath);
my $name=&unescape($foldername);
@@ -3377,7 +3507,17 @@ function go(url) {
if (url!='' && url!= null) {
currentURL = null;
currentSymb= null;
- window.location.href=url;
+ var lcHostname = setLCHost();
+ if (lcHostname!='' && lcHostname!= null) {
+ var RegExp = /^https?\:/;
+ if (RegExp.test(url)) {
+ window.location.href=url;
+ } else {
+ window.location.href=lcHostname+url;
+ }
+ } else {
+ window.location.href=url;
+ }
}
}
@@ -3396,8 +3536,8 @@ ENDUTILITY
sub jump_to_editres {
my ($cfile,$home,$switchserver,$forceedit,$forcereg,$symb,$folderpath,
- $title,$idx,$suppurl,$todocs,$suppanchor) = @_;
- my ($jscall,$anchor);
+ $title,$hostname,$idx,$suppurl,$todocs,$suppanchor) = @_;
+ my ($jscall,$anchor,$usehttp,$usehttps,$is_ext);
if ($switchserver) {
if ($home) {
$cfile = '/adm/switchserver?otherserver='.$home.'&role='.
@@ -3417,9 +3557,37 @@ sub jump_to_editres {
}
} else {
unless ($cfile =~ m{^/priv/}) {
- if ($cfile =~ m{^(/adm/wrapper/ext/[^#]+)#([^#]+)$}) {
+ if ($cfile =~ m{^(/adm/wrapper/ext/([^#]+))#([^#]+)$}) {
$cfile = $1;
- $anchor = $2;
+ my $extlink = $2;
+ $anchor = $3;
+ $is_ext = 1;
+ if (($extlink !~ /^https:/) && ($ENV{'SERVER_PORT'} == 443)) {
+ unless (&Apache::lonnet::uses_sts()) {
+ $usehttp = 1;
+ }
+ } elsif ($env{'request.use_absolute'}) {
+ if ($env{'request.use_absolute'} =~ m{^https://}) {
+ $usehttps = 1;
+ }
+ }
+ } elsif ($cfile =~ m{^/?public/($match_domain)/($match_courseid)/syllabus}) {
+ if ($ENV{'SERVER_PORT'} == 443) {
+ my ($cdom,$cnum) = ($1,$2);
+ if (($env{'request.course.id'}) &&
+ ($env{'course.'.$env{'request.course.id'}.'.num'} eq $cnum) &&
+ ($env{'course.'.$env{'request.course.id'}.'.domain'} eq $cdom)) {
+ if ($env{'course.'.$env{'request.course.id'}.'.externalsyllabus'} =~ m{^http://}) {
+ unless (&Apache::lonnet::uses_sts()) {
+ $usehttp = 1;
+ }
+ }
+ }
+ } elsif ($env{'request.use_absolute'}) {
+ if ($env{'request.use_absolute'} =~ m{^https://}) {
+ $usehttps = 1;
+ }
+ }
}
if ($symb) {
if ($anchor ne '') {
@@ -3445,6 +3613,18 @@ sub jump_to_editres {
}
if ($forceedit) {
$cfile .= (($cfile=~/\?/)?'&':'?').'forceedit=1';
+ if ($usehttps) {
+ $cfile = $env{'request.use_absolute'}.(($cfile =~ /^\//)? '':'/').$cfile;
+ }
+ } elsif ($usehttp) {
+ if ($hostname ne '') {
+ $cfile = 'http://'.$hostname.(($cfile =~ /^\//)? '':'/').$cfile;
+ }
+ unless ($is_ext) {
+ $cfile .= (($cfile=~/\?/)?'&':'?').'usehttp=1';
+ }
+ } elsif ($usehttps) {
+ $cfile = $env{'request.use_absolute'}.(($cfile =~ /^\//)? '':'/').$cfile;
}
if ($forcereg) {
$cfile .= (($cfile=~/\?/)?'&':'?').'register=1';
@@ -3471,15 +3651,18 @@ sub jump_to_editres {
# javascript_valid_email
#
# Generates javascript to validate an e-mail address.
-# Returns a javascript function which accetps a form field as argumnent, and
+# Returns a javascript function which accepts a form field as argument, and
# returns false if field.value does not satisfy two regular expression matches
# for a valid e-mail address. Backwards compatible with old browsers without
# support for javascript RegExp (just checks for @ in field.value in this case).
sub javascript_valid_email {
my $scripttag .= <<'END';
-function validmail(field) {
+function validmail(field,suffix) {
var str = field.value;
+ if (suffix != '' && suffix != undefined) {
+ str += suffix;
+ }
if (window.RegExp) {
var reg1str = "(@.*@)|(\\.\\.)|(@\\.)|(\\.@)|(^\\.)";
var reg2str = "^.+\\@(\\[?)[a-zA-Z0-9\\-\\.]+\\.([a-zA-Z]{2,3}|[0-9]{1,3})(\\]?)$"; //"
@@ -3589,7 +3772,9 @@ sub scripttag {
Constructs a XHTML list from \@array.
-input:
+=over
+
+=item input:
=over
@@ -3603,7 +3788,9 @@ Attributes for
and
passed in a
See htmltag() for more details.
=back
-
+
+=back
+
returns: XHTML list as String.
=cut
@@ -3722,13 +3909,19 @@ should be included in this list.
If the optional headline text is not provided, a default text will be used.
+=over
+
+=item Related routines:
-Related routines:
=over 4
-add_item_funclist
-end_funclist
+
+=item add_item_funclist
+
+=item end_funclist
+
=back
+=back
Inputs: (optional) headline text
@@ -3755,10 +3948,18 @@ sub start_funclist {
Adds an item to the list of available functions
-Related routines:
+=over
+
+=item Related routines:
+
=over 4
-start_funclist
-end_funclist
+
+=item start_funclist
+
+=item end_funclist
+
+=back
+
=back
Inputs: content item with text and link to function
@@ -3781,10 +3982,13 @@ sub add_item_funclist {
End list of available functions
-Related routines:
-=over 4
-start_funclist
-add_item_funclist
+=over
+
+=item Related routines:
+
+ start_funclist
+ add_item_funclist
+
=back
Inputs: ./.
@@ -3817,7 +4021,7 @@ A string that's used as visually highlig
it's value evaluates to false.
=back
-
+
returns: XHTML list as string.
=back
@@ -3830,7 +4034,7 @@ sub funclist_from_array {
$args->{legend} ||= mt('Functions');
return list_from_array( [$args->{legend}, @$items],
{ listattr => {class => 'LC_funclist'} });
-}
+}
=pod
@@ -3852,8 +4056,8 @@ e.g. a file operation in Authoring Space
A reference to the array containing text. Details: sub funclist_from_array
=back
-
-Returns: XHTML div as string.
+
+Returns: XHTML div as string.
=back