--- loncom/interface/lonhtmlcommon.pm 2018/04/29 16:28:25 1.358.2.12 +++ 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.12 2018/04/29 16:28:25 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 ''; } @@ -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; } } ############################################## @@ -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 + +=item Inputs -=over 4 +=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 + +A description of the items being iterated over. Typically 'student'. -=item $extraInfo A description of the items being iterated over. Typically -'student'. +=item $step -=item $step (optional) counter step. Will be set to default 1 if ommited. step must be greater than 0 or empty. +(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(); } @@ -1265,9 +1313,9 @@ sub htmlareaheaders { ENDEDITOR } $s.=(< - - + + + @@ -1304,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 { @@ -1527,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) { @@ -1859,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',''.$alttext.'', $hashref); @@ -1983,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 @@ -1997,7 +2101,9 @@ remaining items in right of breadcrumbs advanced tools shown in a separate box below breadcrumbs line =back - + +=back + returns: nothing =cut @@ -2046,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 @@ -2073,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 @@ -2107,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); @@ -3383,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; + } } } @@ -3402,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='. @@ -3423,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 '') { @@ -3451,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'; @@ -3477,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})(\\]?)$"; //" @@ -3595,7 +3772,9 @@ sub scripttag { Constructs a XHTML list from \@array. -input: +=over + +=item input: =over @@ -3609,7 +3788,9 @@ Attributes for
    and
  • passed in a See htmltag() for more details. =back - + +=back + returns: XHTML list as String. =cut @@ -3728,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 @@ -3761,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 @@ -3787,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: ./. @@ -3823,7 +4021,7 @@ A string that's used as visually highlig it's value evaluates to false. =back - + returns: XHTML list as string. =back @@ -3836,7 +4034,7 @@ sub funclist_from_array { $args->{legend} ||= mt('Functions'); return list_from_array( [$args->{legend}, @$items], { listattr => {class => 'LC_funclist'} }); -} +} =pod @@ -3858,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