--- loncom/interface/lonhtmlcommon.pm 2015/05/05 21:45:55 1.362
+++ loncom/interface/lonhtmlcommon.pm 2025/03/06 16:42:40 1.420
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# a pile of common html routines
#
-# $Id: lonhtmlcommon.pm,v 1.362 2015/05/05 21:45:55 raeburn Exp $
+# $Id: lonhtmlcommon.pm,v 1.420 2025/03/06 16:42:40 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -78,7 +78,12 @@ 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')) ||
+ (($env{'request.deeplink.login'}) && ($env{'request.deeplink.target'} eq '_self'))) {
+ $target ='';
+ }
+ return '&"').'">'.$text.'';
} else {
return '';
}
@@ -92,7 +97,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 +106,14 @@ 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')) ||
+ (($env{'request.deeplink.login'}) && ($env{'request.deeplink.target'} eq '_self'))) {
+ $target='';
+ }
+ return "$linktext";
} else {
- return $linktext;
+ return $linktext;
}
}
##############################################
@@ -221,15 +231,16 @@ sub dependencycheck_js {
$link = '/adm/dependencies?symb='.&HTML::Entities::encode($symb,'<>&"');
} elsif ($folderpath) {
$link = '/adm/dependencies?folderpath='.&HTML::Entities::encode($folderpath,'<>&"');
- $url = $uri;
+ $url = $uri;
} elsif ($uri =~ m{^/public/$match_domain/$match_courseid/syllabus$}) {
$link = '/adm/dependencies';
}
- $link .= (($link=~/\?/)?'&':'?').'title='.
+ $link .= (($link=~/\?/)?'&':'?').'title='.
&HTML::Entities::encode($title,'<>&"');
if ($url) {
$link .= '&url='.&HTML::Entities::encode($url,'<>&"');
}
+ &js_escape(\$link);
return <
// ';
+ $Str .= $special.' />';
return $Str;
}
@@ -484,7 +495,36 @@ the date/time fields are left empty.
=item $state
Specifies the initial state of the form elements. Either 'disabled' or empty.
-Defaults to empty, which indiciates the form elements are not disabled.
+Defaults to empty, which indicates the form elements are not disabled.
+
+=item $no_hh_mm_ss
+
+If true, text boxes for hours, minutes and seconds are omitted.
+
+=item $defhour
+
+Default value for hours (a default of 0 is used otherwise).
+
+=item $defmin
+
+Default value for minutes (a default of 0 is used otherwise).
+
+=item defsec
+
+Default value for seconds (a default of 0 is used otherwise).
+
+=item $nolink
+
+If true, a "Select calendar" link (to pop-up a calendar) is not displayed
+to the right of the items.
+
+=item $no_mm_ss
+
+If true, text boxes for minutes and seconds are omitted.
+
+=item $no_ss
+
+If true, text boxes for seconds are omitted.
=back
@@ -500,15 +540,24 @@ The method used to restrict user input w
##############################################
sub date_setter {
my ($formname,$dname,$currentvalue,$special,$includeempty,$state,
- $no_hh_mm_ss,$defhour,$defmin,$defsec,$nolink) = @_;
+ $no_hh_mm_ss,$defhour,$defmin,$defsec,$nolink,$no_mm_ss,$no_ss) = @_;
my $now = time;
-
+ my %labels = &Apache::lonlocal::texthash(
+ day => 'day',
+ month => 'month',
+ year => 'year',
+ sec => 'seconds',
+ min => 'minutes',
+ hour => 'hours',
+ );
my $tzname;
my ($sec,$min,$hour,$mday,$month,$year) = ('', '', undef,''.''.'');
#other potentially useful values: wkday,yrday,is_daylight_savings
if (! defined($state) || $state ne 'disabled') {
$state = '';
+ } else {
+ $state = 'disabled="disabled"';
}
if (! defined($no_hh_mm_ss)) {
$no_hh_mm_ss = 0;
@@ -601,7 +650,7 @@ document.$formname.$dname\_year.value,
ENDJS
$result .= ' ';
- my $monthselector = qq{\n\n";
return $result;
@@ -818,13 +876,14 @@ parameter setting wizard.
##############################################
sub pjump_javascript_definition {
my $Str = <&"');
&Apache::loncommon::inhibit_menu_check(\$href_path);
if ($form) {
my $href = 'javascript:'.$form.".action='".$href_path."';".$form.'.submit();';
- $output.=qq{$dir/};
+ $output.=qq{$dir/};
} else {
- $output.=qq{$dir/};
+ $output.=qq{$dir/};
}
}
} else {
@@ -1255,9 +1324,9 @@ sub htmlareaheaders {
ENDEDITOR
}
$s.=(<
-
-
+
+
+
@@ -1294,6 +1363,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 {
@@ -1517,62 +1648,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 .= < 1)
+#
+# Will apply to any input tag with class: LC_numresponse_text.
+# Currently set in start_textline for numericalresponse items.
+#
+
+sub dash_to_minus_js {
+ return <<'ENDJS';
+
+
+
+ENDJS
+}
+
############################################################
############################################################
@@ -1766,6 +1912,8 @@ the text on the right side of the breadc
=item $component_help
+the help item filename (without .tex extension).
+
=item $menulink
boolean, controls whether to include a link to /adm/menu
@@ -1774,14 +1922,37 @@ boolean, controls whether to include a l
if 'nohelp' don't include the orange help link
-=item $css_class
+=item $crumbs_style
-optional name for the class to apply to the table for CSS
+optional style attribute for div containing breadcrumbs
+unless called from docs_breadcrumbs
=item $no_mt
optional flag, 1 if &mt() is _not_ to be applied to $component when including the text on the right
+=item $CourseBreadcrumbs
+
+optional flag, 1 if &breadcrumbs called from &docs_breadcrumbs, because breadcrumbs are being
+used to display hierarchy for current folder shown in the Course Editor.
+
+=item $topic_help
+
+optional help item to be displayed on right side of the breadcrumbs row, using
+loncommon::help_open_topic() to generate the link.
+
+=item $topic_help_text
+
+text to include in the link in the optional help item ($topic_help) on the right
+side of the breadcrumbs row.
+
+=item $links_target
+
+optionally includes the target (_top, _parent or _self) for (i) initial
+$menulink item in the breadcrumbs (if present), (ii) return to last location
+(if present), and (iii) help item at the right side of breadcrumbs menu,
+created by loncommon::help_open_topic() or loncommon::help_open_menu().
+
=back
=back
@@ -1812,11 +1983,9 @@ returns: nothing
my %tools = ();
sub breadcrumbs {
- my ($component,$component_help,$menulink,$helplink,$css_class,$no_mt,
- $CourseBreadcrumbs) = @_;
+ my ($component,$component_help,$menulink,$helplink,$crumbs_style,$no_mt,
+ $CourseBreadcrumbs,$topic_help,$topic_help_text,$links_target) = @_;
#
- $css_class ||= 'LC_breadcrumbs';
-
# Make the faq and bug data cascade
my $faq = '';
my $bug = '';
@@ -1829,6 +1998,16 @@ returns: nothing
# The first one should be the course or a menu link
if (!defined($menulink)) { $menulink=1; }
if ($menulink) {
+ if ($env{'request.course.id'}) {
+ my ($menucoll,$deeplinkmenu,$menuref) = &Apache::loncommon::menucoll_in_effect();
+ if (($menucoll) && (ref($menuref) eq 'HASH')) {
+ if ($menuref->{'main'} eq 'n') {
+ undef($menulink);
+ }
+ }
+ }
+ }
+ if ($menulink) {
my $description = 'Menu';
my $no_mt_descr = 0;
if ((exists($env{'request.course.id'})) &&
@@ -1838,7 +2017,7 @@ returns: nothing
$env{'course.'.$env{'request.course.id'}.'.description'};
$no_mt_descr = 1;
if ($env{'request.noversionuri'} =~
- m{^/public/($match_domain)/($match_courseid)/syllabus$}) {
+ m{^/?public/($match_domain)/($match_courseid)/syllabus$}) {
unless (($env{'course.'.$env{'request.course.id'}.'.domain'} eq $1) &&
($env{'course.'.$env{'request.course.id'}.'.num'} eq $2)) {
$description = 'Menu';
@@ -1846,9 +2025,16 @@ returns: nothing
}
}
}
+ my $target = '_top';
+ if ($links_target) {
+ $target = $links_target;
+ } elsif ((($env{'request.lti.login'}) && ($env{'request.lti.target'} eq 'iframe')) ||
+ (($env{'request.deeplink.login'}) && ($env{'request.deeplink.target'} eq '_self'))) {
+ $target='';
+ }
$menulink = { href =>'/adm/menu',
title =>'Go to main menu',
- target =>'_top',
+ target =>$target,
text =>$description,
no_mt =>$no_mt_descr, };
if($last) {
@@ -1866,8 +2052,8 @@ returns: nothing
title => &mt('Back to most recent content resource'),
class => 'LC_menubuttons_link',
};
- if ($env{'request.noversionuri'} eq '/adm/searchcat') {
- $hashref->{'target'} = '_top';
+ if ($links_target) {
+ $hashref->{'target'} = $links_target;
}
$links=&htmltag( 'a','',
$hashref);
@@ -1901,7 +2087,7 @@ returns: nothing
if ($lasttext ne '') {
$links .= &htmltag( 'li', htmltag($CourseBreadcrumbs ? 'b' : 'h1',
- $lasttext), {title => $lasttext});
+ $lasttext));
}
my $icons = '';
@@ -1918,7 +2104,12 @@ returns: nothing
if ($faq ne '' || $component_help ne '' || $bug ne '') {
$icons .= &Apache::loncommon::help_open_menu($component,
$component_help,
- $faq,$bug);
+ $faq,$bug,'','','','',
+ $links_target);
+ }
+ if ($topic_help && $topic_help_text) {
+ $icons .= ' '.&Apache::loncommon::help_open_topic($topic_help,&mt($topic_help_text),'',
+ undef,600,'',$links_target);
}
#
@@ -1932,7 +2123,7 @@ returns: nothing
}
- if ($component) {
+ if (($component) || ($topic_help && $topic_help_text)) {
$links = &htmltag('span',
( $no_mt ? $component : mt($component) ).
( $icons ? $icons : '' ),
@@ -1948,8 +2139,13 @@ returns: nothing
}
if (($links ne '') || ($nav_and_tools)) {
&render_tools(\$links);
- $links = &htmltag('div', $links,
- { id => "LC_breadcrumbs" }) unless ($CourseBreadcrumbs) ;
+ unless ($CourseBreadcrumbs) {
+ my $args = { id => 'LC_breadcrumbs' };
+ if ($crumbs_style ne '') {
+ $args->{'style'} = $crumbs_style;
+ }
+ $links = &htmltag('div', $links, $args);
+ }
}
my $adv_tools = 0;
if (ref($tools{'advtools'}) eq 'ARRAY') {
@@ -1966,9 +2162,8 @@ returns: nothing
# Return the breadcrumb's line
-
-
- return "$links";
+ my $labeltext = &HTML::Entities::encode(&mt('Links for navigation and information'));
+ return '
'.$links.'
';
}
sub clear_breadcrumbs {
@@ -2039,6 +2234,16 @@ returns: nothing
undef(%tools);
}
+=item ¤t_breadcrumb_tools()
+
+returns: a hash containing the current breadcrumb tools.
+
+=cut
+
+ sub current_breadcrumb_tools {
+ return %tools;
+ }
+
=item &render_tools(\$breadcrumbs)
Creates html for breadcrumb tools (categories navigation and tools) and inserts
@@ -2108,7 +2313,7 @@ returns: nothing
} # End of scope for @Crumbs
sub docs_breadcrumbs {
- my ($allowed,$crstype,$contenteditor,$title,$precleared)=@_;
+ my ($allowed,$crstype,$contenteditor,$title,$precleared,$checklinkprot)=@_;
my ($folderpath,@folders,$supplementalflag);
@folders = split('&',$env{'form.folderpath'});
if ($env{'form.folderpath'} =~ /^supplemental/) {
@@ -2123,19 +2328,21 @@ 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);
# each of randompick number, hidden, encrypted, random order, is_page
# are appended with ":"s to the foldername
$name=~s/\:(\d*)\:(\w*)\:(\w*):(\d*)\:?(\d*)$//;
- unless ($supplementalflag) {
- if ($contenteditor) {
+ if ($contenteditor) {
+ if ($supplementalflag) {
+ if ($2) { $ishidden=1; }
+ } else {
if ($1 ne '') {
$randompick=$1;
} else {
@@ -2176,9 +2383,17 @@ sub docs_breadcrumbs {
$plain=~s/\>\;\s*$//;
}
my $menulink = 0;
- if (!$allowed && !$contenteditor) {
+ if (!$allowed && !$contenteditor && !$supplementalflag) {
$menulink = 1;
}
+ if ($checklinkprot) {
+ if ($env{'request.deeplink.login'}) {
+ my $linkprotout = &Apache::lonmenu::linkprot_exit();
+ if ($linkprotout) {
+ &Apache::lonhtmlcommon::add_breadcrumb_tool('tools',$linkprotout);
+ }
+ }
+ }
return (&breadcrumbs(undef,undef,$menulink,'nohelp',undef,undef,
$contenteditor),
$randompick,$ishidden,$isencrypted,$plain,
@@ -2281,7 +2496,7 @@ END
}
sub row_title {
- my ($title,$css_title_class,$css_value_class, $css_value_furtherAttributes) = @_;
+ my ($title,$css_title_class,$css_value_class,$css_value_furtherAttributes,$nocolon) = @_;
$row_count[0]++;
my $css_class = ($row_count[0] % 2)?'LC_odd_row':'LC_even_row';
$css_title_class ||= 'LC_pick_box_title';
@@ -2289,14 +2504,14 @@ sub row_title {
$css_value_class ||= 'LC_pick_box_value';
- if ($title ne '') {
+ if (($title ne '') && (!$nocolon)) {
$title .= ':';
}
my $output = <<"ENDONE";
-
+
$title
-
+
ENDONE
return $output;
@@ -2419,7 +2634,7 @@ sub course_selection {
if ($totcodes > 0) {
my $numtitles = @$codetitles;
if ($numtitles > 0) {
- $output .= ' ';
+ $output .= ' ';
$output .= '
'.$$codetitles[0].' '."\n".
''."\n".
@@ -2552,9 +2767,9 @@ sub course_custom_roles {
sub resource_info_box {
- my ($symb,$onlyfolderflag,$stuvcurrent,$stuvdisp)=@_;
+ my ($symb,$onlyfolderflag,$stuvcurrent,$stuvdisp,$divforres)=@_;
my $return='';
- if ($stuvcurrent ne '') {
+ if (($stuvcurrent ne '') || ($divforres)) {
$return = '