--- loncom/interface/lonhtmlcommon.pm 2018/04/14 02:29:44 1.392 +++ loncom/interface/lonhtmlcommon.pm 2025/03/06 16:51:36 1.421 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # a pile of common html routines # -# $Id: lonhtmlcommon.pm,v 1.392 2018/04/14 02:29:44 raeburn Exp $ +# $Id: lonhtmlcommon.pm,v 1.421 2025/03/06 16:51:36 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -79,7 +79,8 @@ sub coursepreflink { my ($text,$category)=@_; if (&Apache::lonnet::allowed('opa',$env{'request.course.id'})) { my $target =' target="_top"'; - if (($env{'request.lti.login'}) && ($env{'request.lti.target'} eq 'iframe')) { + if ((($env{'request.lti.login'}) && ($env{'request.lti.target'} eq 'iframe')) || + (($env{'request.deeplink.login'}) && ($env{'request.deeplink.target'} eq '_self'))) { $target =''; } return '&"').'">'.$text.''; @@ -105,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; } } ############################################## @@ -225,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{}; @@ -862,13 +876,14 @@ parameter setting wizard. ############################################## sub pjump_javascript_definition { my $Str = < - - + + + @@ -1730,14 +1745,31 @@ sub show_return_link { unless ($env{'request.course.id'}) { return 0; } if ($env{'request.noversionuri'}=~m{^/priv/} || $env{'request.uri'}=~m{^/priv/}) { return 1; } - return if ($env{'request.noversionuri'} eq '/adm/supplemental'); + return if (($env{'request.noversionuri'} eq '/adm/supplemental') && + ($env{'form.folder'} ne 'supplemental')); + return if (($env{'form.folderpath'} ne '') && + (($env{'request.noversionuri'} =~ m{^/adm/$match_domain/$match_username/aboutme$}) || + ($env{'request.noversionuri'} =~ m{^/public/$match_domain/$match_courseid/syllabus$}))); return if (($env{'course.'.$env{'request.course.id'}.'.type'} eq 'Placement') && (!$env{'request.role.adv'})); - if (($env{'request.noversionuri'} =~ m{^/adm/(viewclasslist|navmaps)($|\?)}) + if (($env{'request.noversionuri'} =~ m{^/adm/viewclasslist($|\?)}) || ($env{'request.noversionuri'} =~ m{^/adm/.*/aboutme($|\?)})) { return if ($env{'form.register'}); } + if ((($env{'request.symb'} ne '') || ($env{'form.folderpath'} ne '')) && + ($env{'request.noversionuri'} =~m{^/adm/coursedocs/showdoc/uploaded/($match_domain)/($match_courseid)/(docs|supplemental)/})) { + my ($cdom,$cnum,$area) = ($1,$2,$3); + if (($env{'course.'.$env{'request.course.id'}.'.domain'} eq $cdom) && + ($env{'course.'.$env{'request.course.id'}.'.num'} eq $cnum)) { + if (($env{'request.symb'}) && ($area eq 'docs')) { + my ($map,$resid,$url) = &Apache::lonnet::decode_symb($env{'request.symb'}); + return if ($env{'request.noversionuri'} eq '/adm/coursedocs/showdoc/'.$url); + } elsif (($env{'form.folderpath'}) && ($area eq 'supplemental')) { + return; + } + } + } return (($env{'request.noversionuri'}=~m{^/(res|public)/} && $env{'request.symb'} eq '') || @@ -1806,6 +1838,54 @@ clientTime = (new Date()).getTime(); END } +## +# Client-side javascript to convert any dashes in text pasted +# into textbox(es) for numericalresponse item(s) to a standard +# minus, i.e., - . Calls to dash_to_minus_js() in end_problem() +# and in loncommon::endbodytag() for a .page (arg: dashjs => 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 +} + ############################################################ ############################################################ @@ -1842,9 +1922,10 @@ 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 @@ -1865,6 +1946,13 @@ loncommon::help_open_topic() to generate 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 @@ -1895,11 +1983,9 @@ returns: nothing my %tools = (); sub breadcrumbs { - my ($component,$component_help,$menulink,$helplink,$css_class,$no_mt, - $CourseBreadcrumbs,$topic_help,$topic_help_text,$crstype) = @_; + 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 = ''; @@ -1912,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'})) && @@ -1929,9 +2025,12 @@ returns: nothing } } } - my $target; - unless (($env{'request.lti.login'}) && ($env{'request.lti.target'} eq 'iframe')) { - $target='_top'; + 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', @@ -1953,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',''.$alttext.'', $hashref); @@ -1988,7 +2087,7 @@ returns: nothing if ($lasttext ne '') { $links .= &htmltag( 'li', htmltag($CourseBreadcrumbs ? 'b' : 'h1', - $lasttext), {title => $lasttext}); + $lasttext)); } my $icons = ''; @@ -2005,11 +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); + undef,600,'',$links_target); } # @@ -2039,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') { @@ -2057,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 { @@ -2209,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/) { @@ -2235,8 +2339,10 @@ sub docs_breadcrumbs { # 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 { @@ -2277,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, @@ -2349,7 +2463,7 @@ sub docs_breadcrumbs { my @row_count; sub start_pick_box { - my ($css_class,$id) = @_; + my ($css_class,$id,$caption,$caption_class) = @_; if (defined($css_class)) { $css_class = 'class="'.$css_class.'"'; } else { @@ -2363,6 +2477,16 @@ sub start_pick_box { my $output = <<"END"; END + if (defined($caption)) { + if (defined($caption_class)) { + $caption_class = 'class="'.$caption_class.'"'; + } else { + $caption_class = 'class="LC_caption"'; + } + $output .= <<"END"; + +END + } return $output; } @@ -2382,7 +2506,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'; @@ -2390,14 +2514,14 @@ sub row_title { $css_value_class ||= 'LC_pick_box_value'; - if ($title ne '') { + if (($title ne '') && (!$nocolon)) { $title .= ':'; } my $output = <<"ENDONE"; -
$caption
+ $title - + ENDONE return $output; @@ -2653,9 +2777,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 = '
'; } if ($symb) { @@ -2684,7 +2808,7 @@ sub resource_info_box { } else { $return='

'.&mt('No context provided.').'

'; } - if ($stuvcurrent ne '') { + if (($stuvcurrent ne '') || ($divforres)) { $return .= '
'; } return $return; @@ -3415,12 +3539,18 @@ PARAMSONE if (itemid != null) { itemh = itemid.offsetHeight; } - var primaryheight = document.getElementById('LC_nav_bar').offsetHeight; - var secondaryheight; + var primaryheight = 0; + if (document.getElementById('LC_nav_bar') != null) { + primaryheight = document.getElementById('LC_nav_bar').offsetHeight; + } + var secondaryheight = 0; if (document.getElementById('LC_secondary_menu') != null) { secondaryheight = document.getElementById('LC_secondary_menu').offsetHeight; } - var crumbsheight = document.getElementById('LC_breadcrumbs').offsetHeight; + var crumbsheight = 0; + if (document.getElementById('LC_breadcrumbs') != null) { + crumbsheight = document.getElementById('LC_breadcrumbs').offsetHeight; + } var dccidheight = 0; if (document.getElementById('dccid') != null) { dccidheight = document.getElementById('dccid').offsetHeight; @@ -3493,7 +3623,10 @@ THIRD sub javascript_jumpto_resource { my $confirm_switch = &mt("Editing requires switching to the resource's home server.")."\n". &mt('Switch server?'); + my $confirm_new_tab = &mt("Editing requires using the resource's home server.")."\n". + &mt('Open a new browser tab?'); &js_escape(\$confirm_switch); + &js_escape(\$confirm_new_tab); return (<&'); - if ($symb) { - $cfile .= '&symb='.&HTML::Entities::encode($symb,'"<>&'); + if ($shownsymb) { + $cfile .= '&symb='.&HTML::Entities::encode($shownsymb,'"<>&'); + if ($resedit) { + $cfile .= '&edit=1'; + } } elsif ($folderpath) { $cfile .= '&folderpath='.&HTML::Entities::encode($folderpath,'"<>&'); } @@ -3537,17 +3703,19 @@ sub jump_to_editres { if ($forcereg) { $cfile .= '&register=1'; } - $jscall = "need_switchserver('".&Apache::loncommon::escape_single($cfile)."');"; + $jscall = "need_switchserver('".&Apache::loncommon::escape_single($cfile)."','$target')"; } } else { unless ($cfile =~ m{^/priv/}) { - if ($cfile =~ m{^(/adm/wrapper/ext/([^#]+))#([^#]+)$}) { + if ($cfile =~ m{^(/adm/wrapper/ext/([^#]+))(?:|#([^#]+))$}) { $cfile = $1; my $extlink = $2; $anchor = $3; $is_ext = 1; if (($extlink !~ /^https:/) && ($ENV{'SERVER_PORT'} == 443)) { - $usehttp = 1; + unless ((&Apache::lonnet::uses_sts()) || (&Apache::lonnet::waf_allssl($hostname))) { + $usehttp = 1; + } } elsif ($env{'request.use_absolute'}) { if ($env{'request.use_absolute'} =~ m{^https://}) { $usehttps = 1; @@ -3560,7 +3728,9 @@ sub jump_to_editres { ($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://}) { - $usehttp = 1; + unless ((&Apache::lonnet::uses_sts()) || (&Apache::lonnet::waf_allssl($hostname))) { + $usehttp = 1; + } } } } elsif ($env{'request.use_absolute'}) { @@ -3600,9 +3770,7 @@ sub jump_to_editres { if ($hostname ne '') { $cfile = 'http://'.$hostname.(($cfile =~ /^\//)? '':'/').$cfile; } - unless ($is_ext) { - $cfile .= (($cfile=~/\?/)?'&':'?').'usehttp=1'; - } + $cfile .= (($cfile=~/\?/)?'&':'?').'usehttp=1'; } elsif ($usehttps) { $cfile = $env{'request.use_absolute'}.(($cfile =~ /^\//)? '':'/').$cfile; } @@ -3818,7 +3986,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 @@ -3841,30 +4009,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); }