--- loncom/interface/lonhtmlcommon.pm 2023/01/21 21:20:54 1.358.2.19.2.5 +++ 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.358.2.19.2.5 2023/01/21 21:20:54 raeburn Exp $ +# $Id: lonhtmlcommon.pm,v 1.420 2025/03/06 16:42:40 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -78,11 +78,12 @@ sub java_not_enabled { sub coursepreflink { my ($text,$category)=@_; if (&Apache::lonnet::allowed('opa',$env{'request.course.id'})) { - my $target =' target="_top"'; - if (($env{'request.deeplink.login'}) && ($env{'request.deeplink.target'} eq '_self')) { - $target = ''; - } - 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 ''; } @@ -106,12 +107,13 @@ sub direct_parm_link { $part=&entity_encode($part); if (($symb) && (&Apache::lonnet::allowed('opa')) && ($target ne 'tex')) { my $target=' target="_top"'; - if (($env{'request.deeplink.login'}) && ($env{'request.deeplink.target'} eq '_self')) { - $target = ''; + if ((($env{'request.lti.login'}) && ($env{'request.lti.target'} eq 'iframe')) || + (($env{'request.deeplink.login'}) && ($env{'request.deeplink.target'} eq '_self'))) { + $target=''; } - return "$linktext"; + return "$linktext"; } else { - return $linktext; + return $linktext; } } ############################################## @@ -229,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 < // '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 @@ -636,7 +650,7 @@ document.$formname.$dname\_year.value, ENDJS $result .= ' '; - my $monthselector = qq{}; # Month my @Months = qw/January February March April May June July August September October November December/; @@ -650,11 +664,11 @@ ENDJS } $monthselector.= ' '; # Day - my $dayselector = qq{}; + my $dayselector = qq{}; # Year - my $yearselector = qq{}; + my $yearselector = qq{}; # - my $hourselector = qq{}; if ($includeempty) { $hourselector.=qq{}; } @@ -676,8 +690,8 @@ ENDJS $hourselector .= $timest." \n"; } $hourselector .= " \n"; - my $minuteselector = qq{}; - my $secondselector= qq{}; + my $minuteselector = qq{}; + my $secondselector= qq{}; my $cal_link; unless (($nolink) || ($state eq 'disabled')) { $cal_link = qq{}; @@ -693,11 +707,13 @@ 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, @@ -749,7 +765,9 @@ sub build_url { get_date_from_form retrieves the date specified in an &date_setter form. -Inputs: +=over + +=item Inputs: =over 4 @@ -763,6 +781,8 @@ The unix time to use as the default in c =back +=back + Returns: Unix time represented in the form. =cut @@ -935,7 +955,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' @@ -949,6 +971,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 @@ -996,7 +1020,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 @@ -1010,9 +1034,11 @@ 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 @@ -1022,6 +1048,8 @@ Inputs =back +=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. @@ -1031,7 +1059,9 @@ be used. Updates the text in the progress indicator. Does not increment the count. See &Increment_PrgWin. -Inputs: +=over + +=item Inputs: =over 4 @@ -1043,25 +1073,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 $extraInfo A description of the items being iterated over. Typically -'student'. +=item $prog_state -=item $step (optional) counter step. Will be set to default 1 if ommited. step must be greater than 0 or empty. +Pointer to the data structure returned by Create_PrgWin + +=item $extraInfo + +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. + +=back =back @@ -1072,7 +1115,9 @@ Returns: none Closes the progress window. -Inputs: +=over + +=item Inputs: =over 4 @@ -1082,6 +1127,8 @@ Inputs: =back +=back + Returns: none =back @@ -1277,9 +1324,9 @@ sub htmlareaheaders { ENDEDITOR } $s.=(< - - + + + @@ -1316,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 { @@ -1539,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. - - 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 +} + ############################################################ ############################################################ @@ -1776,20 +1900,62 @@ A link to help for the component will be All inputs can be undef without problems. -Inputs: $component (the text on the right side of the breadcrumbs trail), - $component_help (the help item filename (without .tex extension). - $menulink (boolean, controls whether to include a link to /adm/menu) - $helplink (if 'nohelp' don't include the orange help link) - $css_class (optional name for the class to apply to the table for CSS) - $no_mt (optional flag, 1 if &mt() is _not_ to be applied to $component - when including the text on the right. - $CourseBreadcrumbs (optional flag, 1 if &breadcrumbs called from &docs_breadcrumbs, - because breadcrumbs are being) - $topic_help (optional help item to be displayed on right side of the breadcrumbs - row, using loncommon::help_open_topic() to generate the link. - $topic_help_text (text to include in the link in the optional help item - on the right side of the breadcrumbs row. - $links_target optionally includes the target (_top, _parent or _self) +=over + +=item Inputs: + +=over + +=item $component + +the text on the right side of the breadcrumbs trail + +=item $component_help + +the help item filename (without .tex extension). + +=item $menulink + +boolean, controls whether to include a link to /adm/menu + +=item $helplink + +if 'nohelp' don't include the orange help link + +=item $crumbs_style + +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 Returns a string containing breadcrumbs for the current page. @@ -1817,11 +1983,9 @@ returns: nothing my %tools = (); sub breadcrumbs { - my ($component,$component_help,$menulink,$helplink,$css_class,$no_mt, + 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 = ''; @@ -1864,8 +2028,9 @@ returns: nothing my $target = '_top'; if ($links_target) { $target = $links_target; - } elsif (($env{'request.deeplink.login'}) && ($env{'request.deeplink.target'} eq '_self')) { - $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', @@ -1922,7 +2087,7 @@ returns: nothing if ($lasttext ne '') { $links .= &htmltag( 'li', htmltag($CourseBreadcrumbs ? 'b' : 'h1', - $lasttext), {title => $lasttext}); + $lasttext)); } my $icons = ''; @@ -1974,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') { @@ -1992,9 +2162,8 @@ returns: nothing # Return the breadcrumb's line - - - return "$links"; + my $labeltext = &HTML::Entities::encode(&mt('Links for navigation and information')); + return ''; } sub clear_breadcrumbs { @@ -2013,7 +2182,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 @@ -2027,7 +2198,9 @@ remaining items in right of breadcrumbs advanced tools shown in a separate box below breadcrumbs line =back - + +=back + returns: nothing =cut @@ -2076,8 +2249,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 @@ -2103,8 +2285,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 @@ -2192,7 +2383,7 @@ sub docs_breadcrumbs { $plain=~s/\>\;\s*$//; } my $menulink = 0; - if (!$allowed && !$contenteditor) { + if (!$allowed && !$contenteditor && !$supplementalflag) { $menulink = 1; } if ($checklinkprot) { @@ -2305,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'; @@ -2313,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; @@ -3339,7 +3530,7 @@ PARAMSONE itemh = itemid.offsetHeight; } var primaryheight = 0; - if (document.getElementById('LC_nav_bar') != null) { + if (document.getElementById('LC_nav_bar') != null) { primaryheight = document.getElementById('LC_nav_bar').offsetHeight; } var secondaryheight = 0; @@ -3519,7 +3710,7 @@ sub jump_to_editres { 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); @@ -3719,7 +3910,9 @@ sub scripttag { Constructs a XHTML list from \@array. -input: +=over + +=item input: =over @@ -3733,7 +3926,9 @@ Attributes for
    and
  • passed in a See htmltag() for more details. =back - + +=back + returns: XHTML list as String. =cut @@ -3781,7 +3976,7 @@ sub list_from_array { sub generate_menu { my @menu = @_; # subs for specific html elements - my ($h3, $div, $ul, $li, $a, $img) = inittags( qw(h3 div ul li a img) ); + my ($h2, $div, $ul, $li, $a, $img) = inittags( qw(h2 div ul li a img) ); my @categories; # each element represents the entire markup for a category @@ -3804,30 +3999,25 @@ sub generate_menu { src => $src, alt => mt(defined($$link{alttext}) ? $$link{alttext} : $$link{linktext}) - }), { - href => $$link{url}, - title => mt($$link{linktitle}), - class => 'LC_menubuttons_link' - }). - $a->(mt($$link{linktext}), { + }).mt($$link{linktext}), { href => $$link{url}, title => mt($$link{linktitle}), class => "LC_menubuttons_link" }). - (defined($$link{help}) ? + (defined($$link{help}) ? Apache::loncommon::help_open_topic($$link{help}) : ''), {class => "LC_menubuttons_inline_text"})); } - # wrap categorytitle in

    , concatenate with + # wrap categorytitle in

    , concatenate with # joined and in
      tags wrapped @links # and wrap everything in an enclosing
      and push it into # @categories # such that each element looks like: - #

      title

      • ...
      • ...
      + #

      title

      • ...
      • ...
      # the category won't be added if there aren't any links push(@categories, - $div->($h3->(mt($$category{categorytitle}), {class=>"LC_hcell"}). + $div->($h2->(mt($$category{categorytitle}), {class=>'LC_hcell LC_heading_2'}). $ul->(join('' ,@links), {class =>"LC_ListStyleNormal" }), {class=>"LC_Box LC_400Box"})) if scalar(@links); } @@ -3852,13 +4042,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 @@ -3885,10 +4081,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 @@ -3911,10 +4115,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: ./. @@ -3947,7 +4154,7 @@ A string that's used as visually highlig it's value evaluates to false. =back - + returns: XHTML list as string. =back @@ -3960,7 +4167,7 @@ sub funclist_from_array { $args->{legend} ||= mt('Functions'); return list_from_array( [$args->{legend}, @$items], { listattr => {class => 'LC_funclist'} }); -} +} =pod @@ -3982,8 +4189,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