");
+ $("#LC_rt_"+id).click(editorHandler);
+ });
+
+
+ });
+';
+ $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 .= <'."\n"
+ .'';
return $output;
}
@@ -1173,34 +1496,117 @@ sub htmlareabrowser {
return 1;
}
+#
+# Should the "return to content" link be shown?
+#
+
+sub show_return_link {
+
+ unless ($env{'request.course.id'}) { return 0; }
+ if ($env{'request.noversionuri'}=~m{^/priv/} ||
+ $env{'request.uri'}=~m{^/priv/}) { return 1; }
+
+ if (($env{'request.noversionuri'} =~ m{^/adm/(viewclasslist|navmaps)($|\?)})
+ || ($env{'request.noversionuri'} =~ m{^/adm/.*/aboutme($|\?)})) {
+
+ return if ($env{'form.register'});
+ }
+ return (($env{'request.noversionuri'}=~m{^/(res|public)/} &&
+ $env{'request.symb'} eq '')
+ ||
+ ($env{'request.noversionuri'}=~ m{^/cgi-bin/printout.pl})
+ ||
+ (($env{'request.noversionuri'}=~/^\/adm\//) &&
+ ($env{'request.noversionuri'}!~/^\/adm\/wrapper\//) &&
+ ($env{'request.noversionuri'}!~
+ m{^/adm/.*/(smppg|bulletinboard)($|\?)})
+ ));
+}
+
+
+##
+# Set the dueDate variable...note this is done in the timezone
+# of the browser.
+#
+# @param epoch relative time at which the problem is due.
+#
+# @return the javascript fragment to set the date:
+#
+sub set_due_date {
+ my $dueStamp = shift;
+ my $duems = $dueStamp * 1000; # Javascript Date object needs ms not seconds.
+
+ my $now = time()*1000;
+
+ # This slightly obscure bit of javascript sets the dueDate variable
+ # to the time in the browser at which the problem was due.
+ # The code should correct for gross differences between the server
+ # and client's time setting
+
+ return <<"END";
+
+
+
+END
+}
+##
+# Sets the time at which the problem finished computing.
+# This just updates the serverTime and clientTime variables above.
+# Calling this in e.g. end_problem provides a better estimate of the
+# difference beetween the server and client time setting as
+# the difference contains less of the latency/problem compute time.
+#
+sub set_compute_end_time {
+
+ my $now = time()*1000; # Javascript times are in ms.
+ return <<"END";
+
+
+
+END
+}
+
############################################################
############################################################
=pod
-=item breadcrumbs
+=item &breadcrumbs()
Compiles the previously registered breadcrumbs into an series of links.
-FAQ and BUG links will be placed on the left side of the table if they
-are defined for the last registered breadcrumb.
Additionally supports a 'component', which will be displayed on the
-right side of the table (without a link).
+right side of the breadcrumbs enclosing div (without a link).
A link to help for the component will be included if one is specified.
All inputs can be undef without problems.
-Inputs: $component (the large text on the right side of the table),
+Inputs: $component (the text on the right side of the breadcrumbs trail),
$component_help
$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.
Returns a string containing breadcrumbs for the current page.
-=item clear_breadcrumbs
+=item &clear_breadcrumbs()
Clears the previously stored breadcrumbs.
-=item add_breadcrumb
+=item &add_breadcrumb()
Pushes a breadcrumb on the stack of crumbs.
@@ -1217,66 +1623,90 @@ returns: nothing
############################################################
{
my @Crumbs;
+ my %tools = ();
sub breadcrumbs {
- my ($component,$component_help,$menulink,$helplink,$css_class) = @_;
- #
- $css_class ||= 'LC_breadcrumbs';
- my $Str = "\n".'
';
+ my ($component,$component_help,$menulink,$helplink,$css_class,$no_mt,
+ $CourseBreadcrumbs) = @_;
#
+ $css_class ||= 'LC_breadcrumbs';
+
# Make the faq and bug data cascade
- my $faq = '';
- my $bug = '';
- my $help='';
+ my $faq = '';
+ my $bug = '';
+ my $help = '';
+ # Crumb Symbol
+ my $crumbsymbol = '»';
# The last breadcrumb does not have a link, so handle it separately.
my $last = pop(@Crumbs);
#
# The first one should be the course or a menu link
- if (!defined($menulink)) { $menulink=1; }
+ if (!defined($menulink)) { $menulink=1; }
if ($menulink) {
my $description = 'Menu';
- if (exists($env{'request.course.id'}) &&
- $env{'request.course.id'} ne '') {
+ my $no_mt_descr = 0;
+ if ((exists($env{'request.course.id'})) &&
+ ($env{'request.course.id'} ne '') &&
+ ($env{'course.'.$env{'request.course.id'}.'.description'} ne '')) {
$description =
$env{'course.'.$env{'request.course.id'}.'.description'};
+ $no_mt_descr = 1;
}
- unshift(@Crumbs,{
- href =>'/adm/menu',
- title =>'Go to main menu',
- target =>'_top',
- text =>$description,
- });
- }
- my $links .=
- join('->',
- map {
- $faq = $_->{'faq'} if (exists($_->{'faq'}));
- $bug = $_->{'bug'} if (exists($_->{'bug'}));
- $help = $_->{'help'} if (exists($_->{'help'}));
- my $result = '{'target'}) && $_->{'target'} ne '') {
- $result .= 'target="'.$_->{'target'}.'" ';
- }
- if ($_->{'no_mt'}) {
- $result .='title="'.$_->{'title'}.'">'.
- $_->{'text'}.'';
- } else {
- $result .='title="'.&mt($_->{'title'}).'">'.
- &mt($_->{'text'}).'';
- }
- $result;
- } @Crumbs
- );
- $links .= '->' if ($links ne '');
- if ($last->{'no_mt'}) {
- $links .= ''.$last->{'text'}.'';
- } else {
- $links .= ''.&mt($last->{'text'}).'';
- }
- #
+ $menulink = { href =>'/adm/menu',
+ title =>'Go to main menu',
+ target =>'_top',
+ text =>$description,
+ no_mt =>$no_mt_descr, };
+ if($last) {
+ #$last set, so we have some crumbs
+ unshift(@Crumbs,$menulink);
+ } else {
+ #only menulink crumb present
+ $last = $menulink;
+ }
+ }
+ my $links;
+ if ((&show_return_link) && (!$CourseBreadcrumbs)) {
+ my $alttext = &mt('Go Back');
+ $links=&htmltag( 'a','',
+ { href => '/adm/flip?postdata=return:',
+ title => &mt('Back to most recent content resource'),
+ class => 'LC_menubuttons_link',
+ });
+ $links=&htmltag('li',$links);
+ }
+ $links.= join "",
+ map {
+ $faq = $_->{'faq'} if (exists($_->{'faq'}));
+ $bug = $_->{'bug'} if (exists($_->{'bug'}));
+ $help = $_->{'help'} if (exists($_->{'help'}));
+
+ my $result = $_->{no_mt} ? $_->{text} : &mt($_->{text});
+
+ if ($_->{href}){
+ $result = &htmltag( 'a', $result,
+ { href => $_->{href},
+ title => $_->{no_mt} ? $_->{title} : &mt($_->{title}),
+ target => $_->{target}, });
+ }
+
+ $result = &htmltag( 'li', "$result $crumbsymbol");
+ } @Crumbs;
+
+ #should the last Element be translated?
+
+ my $lasttext = $last->{'no_mt'} ? $last->{'text'}
+ : mt( $last->{'text'} );
+
+ # last breadcrumb is the first order heading of a page
+ # for course breadcrumbs it's just bold
+
+ $links .= &htmltag( 'li', htmltag($CourseBreadcrumbs ? 'b' : 'h1',
+ $lasttext), {title => $lasttext});
+
my $icons = '';
- $faq = $last->{'faq'} if (exists($last->{'faq'}));
- $bug = $last->{'bug'} if (exists($last->{'bug'}));
+ $faq = $last->{'faq'} if (exists($last->{'faq'}));
+ $bug = $last->{'bug'} if (exists($last->{'bug'}));
$help = $last->{'help'} if (exists($last->{'help'}));
$component_help=($component_help?$component_help:$help);
# if ($faq ne '') {
@@ -1285,37 +1715,158 @@ returns: nothing
# if ($bug ne '') {
# $icons .= &Apache::loncommon::help_open_bug($bug);
# }
- if ($faq ne '' || $component_help ne '' || $bug ne '') {
- $icons .= &Apache::loncommon::help_open_menu($component,
- $component_help,
- $faq,$bug);
- }
- #
- $Str .= $links.'
';
- #
- if (defined($component)) {
- $Str .= '
'.
- &mt($component);
- if ($icons ne '') {
- $Str .= ' '.$icons;
- }
- $Str .= '
';
+ if ($faq ne '' || $component_help ne '' || $bug ne '') {
+ $icons .= &Apache::loncommon::help_open_menu($component,
+ $component_help,
+ $faq,$bug);
}
- $Str .= '
'."\n";
#
+
+
+
+ unless ($CourseBreadcrumbs) {
+ $links = &htmltag('ol', $links, { id => "LC_MenuBreadcrumbs" });
+ } else {
+ $links = &htmltag('ul', $links, { class => "LC_CourseBreadcrumbs" });
+ }
+
+
+ if ($component) {
+ $links = &htmltag('span',
+ ( $no_mt ? $component : mt($component) ).
+ ( $icons ? $icons : '' ),
+ { class => 'LC_breadcrumbs_component' } )
+ .$links
+;
+ }
+
+ &render_tools(\$links);
+ $links = &htmltag('div', $links,
+ { id => "LC_breadcrumbs" }) unless ($CourseBreadcrumbs) ;
+ &render_advtools(\$links);
+
# Return the @Crumbs stack to what we started with
push(@Crumbs,$last);
shift(@Crumbs);
- #
- return $Str;
+
+
+ # Return the breadcrumb's line
+
+
+
+ return "$links";
}
sub clear_breadcrumbs {
undef(@Crumbs);
+ undef(%tools);
}
sub add_breadcrumb {
- push (@Crumbs,@_);
+ push(@Crumbs,@_);
+ }
+
+=item &add_breadcrumb_tool($category, $html)
+
+Adds $html to $category of the breadcrumb toolbar container.
+
+$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 navigation
+left of breadcrumbs line
+
+=item tools
+remaining items in right of breadcrumbs line
+
+=item advtools
+advanced tools shown in a separate box below breadcrumbs line
+
+=back
+
+returns: nothing
+
+=cut
+
+ sub add_breadcrumb_tool {
+ my ($category, @html) = @_;
+ return unless @html;
+ if (!keys(%tools)) {
+ %tools = ( navigation => [], tools => [], advtools => []);
+ }
+
+ #this cleans data received from lonmenu::innerregister
+ @html = grep {defined $_ && $_ ne ''} @html;
+ for (@html) {
+ s/align="(right|left)"//;
+# s/// if $category ne 'advtools';
+ }
+
+ push @{$tools{$category}}, @html;
+ }
+
+=item &clear_breadcrumb_tools()
+
+Clears the breadcrumb toolbar container.
+
+returns: nothing
+
+=cut
+
+ sub clear_breadcrumb_tools {
+ undef(%tools);
+ }
+
+=item &render_tools(\$breadcrumbs)
+
+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.
+
+returns: nothing
+
+=cut
+
+#TODO might split this in separate functions for each category
+ sub render_tools {
+ my ($breadcrumbs) = @_;
+ return unless (keys(%tools));
+
+ my $navigation = list_from_array($tools{navigation},
+ { listattr => { class=>"LC_breadcrumb_tools_navigation" } });
+ my $tools = list_from_array($tools{tools},
+ { listattr => { class=>"LC_breadcrumb_tools_tools" } });
+ $$breadcrumbs = list_from_array([$navigation, $tools, $$breadcrumbs],
+ { listattr => { class=>'LC_breadcrumb_tools_outerlist' } });
+ }
+
+=pod
+
+=item &render_advtools(\$breadcrumbs)
+
+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).
+
+returns: nothing
+
+=cut
+
+ sub render_advtools {
+ my ($breadcrumbs) = @_;
+ return unless (defined $tools{'advtools'})
+ and (scalar(@{$tools{'advtools'}}) > 0);
+
+ $$breadcrumbs .= Apache::loncommon::head_subbox(
+ funclist_from_array($tools{'advtools'}) );
}
} # End of scope for @Crumbs
@@ -1334,7 +1885,7 @@ returns: nothing
# row1
# row2
# row3 ... etc.
-# &submit_row(0
+# &submit_row()
# &end_pick_box()
#
# where row1, row 2 etc. are chosen from &role_select_row,&course_select_row,
@@ -1376,40 +1927,60 @@ returns: nothing
# routines, but can also be called directly to start and end rows which have
# needs that are not accommodated by the *_select_row() routines.
+{ # Start: row_count block for pick_box
+my @row_count;
+
sub start_pick_box {
- my ($css_class) = @_;
+ my ($css_class,$id) = @_;
if (defined($css_class)) {
$css_class = 'class="'.$css_class.'"';
} else {
$css_class= 'class="LC_pick_box"';
}
+ my $table_id;
+ if (defined($id)) {
+ $table_id = ' id="'.$id.'"';
+ }
+ unshift(@row_count,0);
my $output = <<"END";
-
+
END
return $output;
}
sub end_pick_box {
+ shift(@row_count);
my $output = <<"END";
END
return $output;
}
+sub row_headline {
+ my $output = <<"END";
+
+END
+ return $output;
+}
+
sub row_title {
- my ($title,$css_title_class,$css_value_class) = @_;
+ my ($title,$css_title_class,$css_value_class, $css_value_furtherAttributes) = @_;
+ $row_count[0]++;
+ my $css_class = ($row_count[0] % 2)?'LC_odd_row':'LC_even_row';
$css_title_class ||= 'LC_pick_box_title';
$css_title_class = 'class="'.$css_title_class.'"';
$css_value_class ||= 'LC_pick_box_value';
- $css_value_class = 'class="'.$css_value_class.'"';
+ if ($title ne '') {
+ $title .= ':';
+ }
my $output = <<"ENDONE";
-
+
- $title:
+ $title
-
+
ENDONE
return $output;
}
@@ -1431,14 +2002,20 @@ ENDTWO
return $output;
}
+} # End: row_count block for pick_box
+
sub role_select_row {
my ($roles,$title,$css_class,$show_separate_custom,$cdom,$cnum) = @_;
+ my $crstype = 'Course';
+ if ($cdom ne '' && $cnum ne '') {
+ $crstype = &Apache::loncommon::course_type($cdom.'_'.$cnum);
+ }
my $output;
if (defined($title)) {
$output = &row_title($title,$css_class);
}
$output .= qq|
-