--- loncom/interface/lonhtmlcommon.pm 2007/09/27 15:36:23 1.164
+++ loncom/interface/lonhtmlcommon.pm 2010/01/25 19:16:08 1.263
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# a pile of common html routines
#
-# $Id: lonhtmlcommon.pm,v 1.164 2007/09/27 15:36:23 raeburn Exp $
+# $Id: lonhtmlcommon.pm,v 1.263 2010/01/25 19:16:08 faziophi Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -62,6 +62,100 @@ use Apache::lonlocal;
use Apache::lonnet;
use LONCAPA;
+
+sub coursepreflink {
+ my ($text,$category)=@_;
+ if (&Apache::lonnet::allowed('opa',$env{'request.course.id'})) {
+ return '&"').'">'.$text.'';
+ } else {
+ return '';
+ }
+}
+
+sub raw_href_to_link {
+ my ($message)=@_;
+ $message=~s/(https?\:\/\/[^\s\'\"]+)(\s|$)/$1<\/tt><\/a>$2/gi;
+ return $message;
+}
+
+##############################################
+##############################################
+
+=item confirm_success
+
+Successful completion of an operation message
+
+=cut
+
+sub confirm_success {
+ my ($message,$failure)=@_;
+ if ($failure) {
+ return ''."\n"
+ .' '."\n"
+ .$message."\n"
+ .''."\n";
+ } else {
+ return ''."\n"
+ .' '."\n"
+ .$message."\n"
+ .''."\n";
+ }
+}
+
+##############################################
+##############################################
+
+=pod
+
+=item dragmath_button
+
+Creates a button that launches a dragmath popup-window, in which an
+expression can be edited and pasted as LaTeX into a specified textarea.
+
+ textarea - Name of the textarea to edit.
+ helpicon - If true, show a help icon to the right of the button.
+
+=cut
+
+sub dragmath_button {
+ my ($textarea,$helpicon) = @_;
+ my $help_text;
+ if ($helpicon) {
+ $help_text = &Apache::loncommon::help_open_topic('Authoring_Math_Editor');
+ }
+ my $buttontext=&mt('Edit Math');
+ return <$help_text
+ENDDRAGMATH
+}
+
+##############################################
+
+=pod
+
+=item dragmath_js
+
+Javascript used to open pop-up window containing dragmath applet which
+can be used to paste LaTeX into a textarea.
+=cut
+
+sub dragmath_js {
+ my ($popup) = @_;
+ return <
+ //
+
+
+ENDDRAGMATHJS
+}
+
+
##############################################
##############################################
@@ -79,10 +173,10 @@ sub authorbombs {
$url=&Apache::lonnet::declutter($url);
my ($udom,$uname)=($url=~m{^($LONCAPA::domain_re)/($LONCAPA::username_re)/});
my %bombs=&Apache::lonmsg::all_url_author_res_msg($uname,$udom);
- foreach (keys %bombs) {
- if ($_=~/^$udom\/$uname\//) {
+ foreach my $bomb (keys(%bombs)) {
+ if ($bomb =~ /^$udom\/$uname\//) {
return ''.
+ '">'.
&Apache::loncommon::help_open_topic('About_Bombs');
}
}
@@ -141,6 +235,9 @@ sub select_recent {
unless ($value =~/^error\:/) {
my $escaped = &Apache::loncommon::escape_url($value);
&Apache::loncommon::inhibit_menu_check(\$escaped);
+ if ($area eq 'residx') {
+ next if ((!&Apache::lonnet::allowed('bre',$value)) && (!&Apache::lonnet::allowed('bro',$value)));
+ }
$return.="\n';
@@ -158,7 +255,7 @@ sub get_recent {
# Begin filling return_hash with any 'always_include' option
my %time_hash = ();
my %return_hash = ();
- foreach my $item (keys %recent) {
+ foreach my $item (keys(%recent)) {
my ($thistime,$thisvalue)=(split(/\&/,$recent{$item}));
if ($thistime eq 'always_include') {
$return_hash{$item} = &unescape($thisvalue);
@@ -231,7 +328,7 @@ sub checkbox {
$Str .= 'value="'.$value.'"';
}
if ($checked) {
- $Str .= ' checked="1"';
+ $Str .= ' checked="checked"';
}
$Str .= ' />';
return $Str;
@@ -253,7 +350,7 @@ sub radio {
$Str .= 'value="'.$value.'"';
}
if ($checked eq $value) {
- $Str .= ' checked="1"';
+ $Str .= ' checked="checked"';
}
$Str .= ' />';
return $Str;
@@ -283,7 +380,8 @@ dname_hour, dname_min, and dname_sec.
The current setting for this time parameter. A unix format time
(time in seconds since the beginning of Jan 1st, 1970, GMT.
-An undefined value is taken to indicate the value is the current time.
+An undefined value is taken to indicate the value is the current time
+unless it is requested to leave it empty. See $includeempty.
Also, to be explicit, a value of 'now' also indicates the current time.
=item $special
@@ -293,6 +391,9 @@ the date_setter. See lonparmset for exa
=item $includeempty
+If it is set (true) and no date/time value is provided,
+the date/time fields are left empty.
+
=item $state
Specifies the initial state of the form elements. Either 'disabled' or empty.
@@ -311,7 +412,12 @@ The method used to restrict user input w
sub date_setter {
my ($formname,$dname,$currentvalue,$special,$includeempty,$state,
$no_hh_mm_ss,$defhour,$defmin,$defsec,$nolink) = @_;
- my $wasdefined=1;
+ my $now = time;
+
+ my $tzname;
+ my ($sec,$min,$hour,$mday,$month,$year) = ('', '', undef,''.''.'');
+ #other potentially useful values: wkday,yrday,is_daylight_savings
+
if (! defined($state) || $state ne 'disabled') {
$state = '';
}
@@ -319,40 +425,29 @@ sub date_setter {
$no_hh_mm_ss = 0;
}
if ($currentvalue eq 'now') {
- $currentvalue=time;
+ $currentvalue = $now;
}
- if ((!defined($currentvalue)) || ($currentvalue eq '')) {
- $wasdefined=0;
- if ($includeempty) {
- $currentvalue = 0;
- } else {
- $currentvalue = time;
- }
+
+ # Default value: Set empty date field to current time
+ # unless empty inclusion is requested
+ if ((!$includeempty) && (!$currentvalue)) {
+ $currentvalue = $now;
}
- # other potentially useful values: wkday,yrday,is_daylight_savings
- my ($sec,$min,$hour,$mday,$month,$year)=('','',undef,'','','');
+ # Do we have a date? Split it!
if ($currentvalue) {
- ($sec,$min,$hour,$mday,$month,$year,undef,undef,undef) =
- localtime($currentvalue);
- $year += 1900;
- }
- unless ($wasdefined) {
- if (($defhour) || ($defmin) || ($defsec)) {
- ($sec,$min,$hour,$mday,$month,$year,undef,undef,undef) =
- localtime(time);
- $year += 1900;
- $sec=($defsec?$defsec:0);
- $min=($defmin?$defmin:0);
- $hour=($defhour?$defhour:0);
- } elsif (!$includeempty) {
- $sec=0;
- $min=0;
- $hour=0;
- }
+ ($tzname,$sec,$min,$hour,$mday,$month,$year) = &get_timedates($currentvalue);
+
+ #No values provided for hour, min, sec? Use default 0
+ if (($defhour) || ($defmin) || ($defsec)) {
+ $sec = ($defsec ? $defsec : 0);
+ $min = ($defmin ? $defmin : 0);
+ $hour = ($defhour ? $defhour : 0);
+ }
}
my $result = "\n\n";
$result .= <
+//
ENDJS
- $result .= ' ';
+ $result .= ' ';
my $monthselector = qq{';
# Day
my $dayselector = qq{};
# Year
- my $yearselector = qq{};
+ my $yearselector = qq{};
#
my $hourselector = qq{';
+
+ return $output;
}
# --------------------- A function that generates a window for the spellchecker
@@ -1042,6 +1192,7 @@ sub spellheader {
my $nothing=&javascript_nothing();
return (<
+//
+// ]]>
ENDCHECK
}
@@ -1085,44 +1237,18 @@ ENDLINK
}
sub htmlareaheaders {
- if (&htmlareablocked()) { return ''; }
- unless (&htmlareabrowser()) { return ''; }
- my $lang='en';
- if (&mt('htmlarea_lang') ne 'htmlarea_lang') {
- $lang=&mt('htmlarea_lang');
- }
- return (<
-_editor_url='/htmlarea/';
-_editor_lang='$lang';
-
-
-
-ENDHEADERS
-}
-
-# ------------------------------------------------- Activate additional buttons
-
-sub htmlareaaddbuttons {
- if (&htmlareablocked()) { return ''; }
- unless (&htmlareabrowser()) { return ''; }
- return (<\$','\$ ');
- }
- );
- config.registerButton('ed_math_eqn','LaTeX Equation',
- '/htmlarea/images/ed_math_eqn.gif',false,
- function(editor,id) {
- editor.surroundHTML(
- ' \\n
\\\\[','\\\\]
\\n ');
- }
- );
- config.toolbar.push(['ed_math','ed_math_eqn']);
-ENDADDBUTTON
+ my $s="";
+ if (&htmlareabrowser()) {
+ $s.=(<
+ENDEDITOR
+ }
+ $s.=(<
+
+
+ENDJQUERY
+ return $s;
}
# ----------------------------------------------------------------- Preferences
@@ -1143,18 +1269,95 @@ sub enablelink {
return ''.&mt('Enable WYSIWYG Editor').'';
}
+# ------------------------------------------------- lang to use in html editor
+sub htmlarea_lang {
+ my $lang='en';
+ if (&mt('htmlarea_lang') ne 'htmlarea_lang') {
+ $lang=&mt('htmlarea_lang');
+ }
+ return $lang;
+}
+
# ----------------------------------------- Script to activate only some fields
sub htmlareaselectactive {
my @fields=@_;
unless (&htmlareabrowser()) { return ''; }
- if (&htmlareablocked()) { return ' '.&enablelink(@fields); }
- my $output=' ".
+
+ function startRichEditor(id) {
+ CKEDITOR.replace(id,
+ {
+ customConfig: "/ckeditor/loncapaconfig.js"
+ }
+ );
+ }
+
+ function destroyRichEditor(id) {
+ CKEDITOR.instances[id].destroy();
+ }
+
+ function editorHandler(event) {
+ var rawid = $(this).attr("id");
+ var id = new RegExp("LC_rt_(.*)").exec(rawid)[1]
+ event.preventDefault();
+ if ($(this).hasClass("LC_enable_rt")) {
+ startRichEditor(id);
+ $("#LC_rt_"+id).html("« Plain text");
+ $("#LC_rt_"+id).attr("title", "Disable rich text formatting and edit in plain text");
+ $("#LC_rt_"+id).addClass("LC_disable_rt");
+ $("#LC_rt_"+id).removeClass("LC_enable_rt");
+ } else {
+ destroyRichEditor(id);
+ $("#LC_rt_"+id).html("Rich formatting »");
+ $("#LC_rt_"+id).attr("title", "Enable rich text formatting (bold, italic, etc.)");
+ $("#LC_rt_"+id).addClass("LC_enable_rt");
+ $("#LC_rt_"+id).removeClass("LC_disable_rt");
+ }
+ }
+
+ $(document).ready(function(){
+ $(".LC_richAlwaysOn").each(function() {
+ startRichEditor($(this).attr("id"));
+ });
+ $(".LC_richDetectHtml").each(function() {
+ var id = $(this).attr("id");
+ if(containsBlockHtml(id)) {
+ $(this).before("
");
+ $("#LC_rt_"+id).click(editorHandler);
+ });
+
+ });
+';
+ $output.="\nwindow.status='Activated Editfields';\n"
+ .'// ]]>'."\n"
+ .' '.
&disablelink(@fields);
return $output;
}
@@ -1180,19 +1383,19 @@ sub htmlareabrowser {
=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
@@ -1216,66 +1419,74 @@ 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';
+ my $no_mt_descr = 0;
if (exists($env{'request.course.id'}) &&
$env{'request.course.id'} 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 = 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'} );
+
+ $links .= htmltag( 'li', htmltag('b', $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 '') {
@@ -1284,37 +1495,146 @@ 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
+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 (!defined(%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 defined %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' } });
+ }
+
+=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
@@ -1333,7 +1653,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,
@@ -1375,6 +1695,9 @@ 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) = @_;
if (defined($css_class)) {
@@ -1382,6 +1705,7 @@ sub start_pick_box {
} else {
$css_class= 'class="LC_pick_box"';
}
+ unshift(@row_count,0);
my $output = <<"END";
END
@@ -1389,26 +1713,38 @@ END
}
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;
}
@@ -1430,14 +1766,21 @@ 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|
-
';
}
}
- $output .= ''.&mt('Pick specific course(s):').' '.$courseform.' selected. '."\n";
- $output .= &row_closure();
+ $output .= ''.$pickspec.' '.$courseform.' selected. '."\n";
return $output;
}
@@ -1558,7 +1919,7 @@ sub status_select_row {
$output = &row_title($title,$css_class,'LC_pick_box_select');
}
$output .= qq|
- \n|;
+ \n|;
foreach my $status_type (sort(keys(%{$types}))) {
$output .= ' ';
}
@@ -1632,7 +1993,28 @@ sub course_custom_roles {
##############################################
##############################################
-
+
+# topic_bar
+#
+# Generates a div containing an (optional) number with a white background followed by a
+# title with a background color defined in the corresponding CSS: LC_topic_bar
+# Inputs:
+# 1. number to display.
+# If input for number is empty only the title will be displayed.
+# 2. title text to display.
+# Outputs - a scalar containing html mark-up for the div.
+
+sub topic_bar {
+ my ($num,$title) = @_;
+ my $number = '';
+ if ($num ne '') {
+ $number = ''.$num.'';
+ }
+ return '