--- loncom/interface/lonnavmaps.pm 2017/08/21 21:29:56 1.533 +++ loncom/interface/lonnavmaps.pm 2017/09/13 23:35:07 1.536 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # Navigate Maps Handler # -# $Id: lonnavmaps.pm,v 1.533 2017/08/21 21:29:56 raeburn Exp $ +# $Id: lonnavmaps.pm,v 1.536 2017/09/13 23:35:07 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -501,7 +501,7 @@ use Apache::lonlocal; use Apache::lonnet; use Apache::lonmap; -use POSIX qw (floor strftime); +use POSIX qw (ceil floor strftime); use Time::HiRes qw( gettimeofday tv_interval ); use LONCAPA; use DateTime(); @@ -2290,7 +2290,7 @@ sub generate_email_discuss_status { foreach my $msgid (@keys) { if ((!$emailstatus{$msgid}) || ($emailstatus{$msgid} eq 'new')) { my ($sendtime,$shortsubj,$fromname,$fromdomain,$status,$fromcid, - $symb,$error) = &Apache::lonmsg::unpackmsgid($msgid); + $symb,$error) = &Apache::lonmsg::unpackmsgid(&LONCAPA::escape($msgid)); &Apache::lonenc::check_decrypt(\$symb); if (($fromcid ne '') && ($fromcid ne $cid)) { next; @@ -2882,40 +2882,89 @@ sub recurseup_maps { } sub recursed_crumbs { - my ($self,$mapurl) = @_; + my ($self,$mapurl,$restitle) = @_; my (@revmapinfo,@revmapres); my $mapres = $self->getResourceByUrl($mapurl); if (ref($mapres)) { - @revmapres = map { $self->getByMapPc($_); } split(/,/,$mapres->map_hierarchy()); + @revmapres = map { $self->getByMapPc($_); } split(/,/,$mapres->map_breadcrumbs()); shift(@revmapres); - push(@revmapres,$mapres); } - my %toplevel; + my $allowedlength = 60; + my $minlength = 5; + my $allowedtitle = 30; + if (($env{'environment.icons'} eq 'iconsonly') && (!$env{'browser.mobile'})) { + $allowedlength = 100; + $allowedtitle = 70; + } + if (length($restitle) > $allowedtitle) { + $restitle = &truncate_crumb_text($restitle,$allowedtitle); + } + my $totallength = length($restitle); + my @links; + foreach my $map (@revmapres) { my $pc = $map->map_pc(); next if ((!$pc) || ($pc == 1)); - my $func = sub { return ($_[0]->src() ne $map->src); }; - my @resources = $self->retrieveResources($map->src,$func,0); - my $count = 0; - my $notmap = 0; - foreach my $res (@resources) { - next unless (ref($res)); - my $symb = $res->symb(); - unless ($toplevel{$symb}) { - $toplevel{$symb} = $res->src; - $count ++; - unless ($res->is_map()) { - $notmap ++; + push(@links,$map); + push(@revmapinfo,{'href' => $map->link().'?navmap=1','text' => $map->title(),'no_mt' => 1,}); + $totallength += length($map->title()); + } + my $numlinks = scalar(@links); + if ($numlinks) { + if ($totallength - $allowedlength > 0) { + my $available = $allowedlength - length($restitle); + my $avg = POSIX::ceil($available/$numlinks); + if ($avg < $minlength) { + $avg = $minlength; + } + @revmapinfo = (); + foreach my $map (@links) { + my $showntitle = &truncate_crumb_text($map->title(),$avg); + if ($showntitle ne '') { + push(@revmapinfo,{'href' => $map->link().'?navmap=1','text' => $showntitle,'no_mt' => 1,}); } } } - if (($count > 1) || ($count && $notmap)) { - push(@revmapinfo,{'href' => $map->link().'?navmap=1','text' => $map->title(),'no_mt' => 1,}); - } + } + if ($restitle ne '') { + push(@revmapinfo,{'text' => $restitle, 'no_mt' => 1}); } return @revmapinfo; } +sub truncate_crumb_text { + my ($title,$limit) = @_; + my $showntitle = ''; + if (length($title) > $limit) { + my @words = split(/\b\s*/,$title); + if (@words == 1) { + $showntitle = substr($title,0,$limit).' ...'; + } else { + my $linklength = 0; + my $num = 0; + foreach my $word (@words) { + $linklength += 1+length($word); + if ($word eq '-') { + $showntitle =~ s/ $//; + $showntitle .= $word; + } elsif ($linklength > $limit) { + if ($num < @words) { + $showntitle .= $word.' ...'; + last; + } else { + $showntitle .= $word; + } + } else { + $showntitle .= $word.' '; + } + } + $showntitle =~ s/ $//; + } + return $showntitle; + } else { + return $title; + } +} # # Determines the open/close dates for printing a map that @@ -4564,6 +4613,12 @@ Returns a string with a comma-separated for the hierarchy of maps containing a map, with the top level map first, then descending to deeper levels, with the enclosing map last. +=item * B: + +Same as map_hierarchy, except maps containing only a single itemm if +it's a map, or containing no items are omitted, unless it's the top +level map (map_pc = 1), which is always included. + =back =cut @@ -4599,6 +4654,11 @@ sub map_hierarchy { my $pc = $self->map_pc(); return $self->navHash("map_hierarchy_$pc", 0); } +sub map_breadcrumbs { + my $self = shift; + my $pc = $self->map_pc(); + return $self->navHash("map_breadcrumbs_$pc", 0); +} ##### # Property queries