--- loncom/interface/lonhtmlcommon.pm	2012/05/28 13:09:17	1.314
+++ loncom/interface/lonhtmlcommon.pm	2012/11/27 23:45:08	1.332
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # a pile of common html routines
 #
-# $Id: lonhtmlcommon.pm,v 1.314 2012/05/28 13:09:17 raeburn Exp $
+# $Id: lonhtmlcommon.pm,v 1.332 2012/11/27 23:45:08 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -61,7 +61,7 @@ use Time::HiRes;
 use Apache::lonlocal;
 use Apache::lonnet;
 use HTML::Entities();
-use LONCAPA;
+use LONCAPA qw(:DEFAULT :match);
 
 sub java_not_enabled {
    return "\n".'<span class="LC_error">'.
@@ -95,7 +95,7 @@ sub direct_parm_link {
     $filter=&entity_encode($filter);
     $part=&entity_encode($part);
     if (($symb) && (&Apache::lonnet::allowed('opa')) && ($target ne 'tex')) {
-       return "<a target='_top' href='/adm/parmset?symb=$symb&filter=$filter&part=$part'><span class='LC_setting'>$linktext</span></a>";
+       return "<a target='_top' href='/adm/parmset?symb=$symb&amp;filter=$filter&amp;part=$part'><span class='LC_setting'>$linktext</span></a>";
     } else {
        return $linktext;
     }
@@ -209,9 +209,10 @@ dependencies for a web page uploaded dir
 =cut
 
 sub dependencycheck_js {
-    my ($symb,$title) = @_;
+    my ($symb,$title,$url) = @_;
     my $link = '/adm/dependencies?symb='.&HTML::Entities::encode($symb,'<>&"').
-               '&title='.&HTML::Entities::encode($title,'<>&"');
+               '&title='.&HTML::Entities::encode($title,'<>&"').
+               '&url='.&HTML::Entities::encode($url,'<>&"');
     return <<ENDJS;
                 <script type="text/javascript">
                 // <![CDATA[
@@ -1100,6 +1101,7 @@ sub Close_PrgWin {
     undef(%$prog_state);
 }
 
+
 # ------------------------------------------------------- Puts directory header
 
 sub crumbs {
@@ -1210,6 +1212,10 @@ ENDEDITOR
 <link rel="stylesheet" type="text/css" href="/adm/jpicker/css/jPicker-1.1.6.min.css" />
 <script type="text/javascript" src="/adm/countdown/js/jquery.countdown.js"></script>
 <link rel="stylesheet" type="text/css" href="/adm/countdown/css/jquery.countdown.css" />
+
+<script type="text/javascript" src="/adm/spellchecker/js/jquery.spellchecker.min.js"></script>
+<link rel="stylesheet" type="text/css" href="/adm/spellchecker/css/spellchecker.css" />
+
 ENDJQUERY
 	return $s;
 }
@@ -1225,6 +1231,17 @@ sub htmlarea_lang {
     return $lang;
 }
 
+# return javacsript to activate elements of .colorchooser with jpicker:
+# Caller is responsible for enclosing this in <script> tags:
+#
+sub color_picker {
+    return '
+$(document).ready(function(){
+    $.fn.jPicker.defaults.images.clientPath="/adm/jpicker/images/";
+    $(".colorchooser").jPicker({window: { position: {x: "screenCenter", y: "bottom"}}});
+});';
+}
+
 # ----------------------------------------- Script to activate only some fields
 
 sub htmlareaselectactive {
@@ -1338,12 +1355,12 @@ sub htmlareaselectactive {
 			$(this).before("<div><a href=\"#\" id=\"LC_rt_"+id+"\" title=\"Enable rich text formatting (bold, italic, etc.)\" class=\"LC_enable_rt\"><b>Rich formatting &raquo;</b></a></div>");
 			$("#LC_rt_"+id).click(editorHandler);
 		});
-                $.fn.jPicker.defaults.images.clientPath="/adm/jpicker/images/";
-                $(".colorchooser").jPicker();
 
 
 	});
 ';
+    $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.
@@ -1397,6 +1414,40 @@ sub htmlareaselectactive {
       });
    }
 });
+
+    /* This code describes the spellcheck options that will be used for
+       items with class 'spellchecked'.  It is necessary for those objects'
+       to explicitly request checking (e.g. onblur is a nice event for that).
+     */
+     \$(document).ready(function() {
+	 \$(".spellchecked").spellchecker({
+	   url: "/ajax/spellcheck",
+	   lang: "en",                      
+	   engine: "pspell",
+	   suggestionBoxPosition: "below",
+	   innerDocument: true
+					  });
+	 \$("textarea.spellchecked").spellchecker({
+	   url: "/ajax/spellcheck",
+	   lang: "en",                      
+	   engine: "pspell",
+	   suggestionBoxPosition: "below",
+	   innerDocument: true
+					  });
+
+			});
+
+    /* the muli colored editor can generate spellcheck with language 'none'
+       to disable spellcheck as well
+    */
+    function doSpellcheck(element, lang) {
+	if (lang != 'none') {
+ 	    \$(element).spellchecker('option', {lang: lang});
+	    \$(element).spellchecker('check');
+        }
+    }
+
+
 JAVASCRIPT
     if ($dragmath_prefix ne '') {
         $output .= '
@@ -1453,7 +1504,8 @@ sub show_return_link {
 
     unless ($env{'request.course.id'}) { return 0; }
     if ($env{'request.noversionuri'}=~m{^/priv/} ||
-        $env{'request.uri'}=~m{^/~}) { return 1; }
+        $env{'request.uri'}=~m{^/priv/}) { return 1; }
+    return if ($env{'request.noversionuri'} eq '/adm/supplemental');
 
     if (($env{'request.noversionuri'} =~ m{^/adm/(viewclasslist|navmaps)($|\?)})
         || ($env{'request.noversionuri'} =~ m{^/adm/.*/aboutme($|\?)})) {
@@ -1492,8 +1544,9 @@ sub set_due_date {
     # The code should correct for gross differences between the server
     # and client's time setting
 
-    my $js = "
-<script type='text/javascript'>
+     return <<"END";
+
+<script type="text/javascript">
   //<![CDATA[
 var serverDueDate = $duems;
 var serverTime    = $now;
@@ -1502,9 +1555,8 @@ var dueDate       = new Date(serverDueDa
 
   //]]>
 </script>
-";
 
-    return $js;
+END
 }
 ##
 # Sets the time at which the problem finished computing.
@@ -1516,17 +1568,16 @@ var dueDate       = new Date(serverDueDa
 sub set_compute_end_time {
 
     my $now = time()*1000;	# Javascript times are in ms.
-    my $js = "
-<script type='text/javascript'>
+    return <<"END";
+
+<script type="text/javascript">
 //<![CDATA[
 serverTime = $now;
 clientTime = (new Date()).getTime();
 //]]>
 </script>
 
-";
-    return $js;
-    
+END
 }
 
 ############################################################
@@ -1601,6 +1652,14 @@ returns: nothing
                 $description = 
                     $env{'course.'.$env{'request.course.id'}.'.description'};
                 $no_mt_descr = 1;
+                if ($env{'request.noversionuri'} =~ 
+                    m{^/public/($match_domain)/($match_courseid)/syllabus$}) {
+                    unless (($env{'course.'.$env{'request.course.id'}.'.domain'} eq $1) &&
+                            ($env{'course.'.$env{'request.course.id'}.'.num'} eq $2)) {
+                        $description = 'Menu';
+                        $no_mt_descr = 0;
+                    }
+                }
             }
             $menulink =  {  href   =>'/adm/menu',
                             title  =>'Go to main menu',
@@ -1616,11 +1675,13 @@ returns: nothing
             }
         }
         my $links;
-        if ((&show_return_link) && (!$CourseBreadcrumbs)) {
+        if ((&show_return_link) && (!$CourseBreadcrumbs) && (ref($last) eq 'HASH')) {
             my $alttext = &mt('Go Back');
-            $links=&htmltag( 'a',"<img src='/res/adm/pages/reload.png' border='0' style='vertical-align:middle;' alt='$alttext' />",
+            $links=&htmltag( 'a','<img src="/res/adm/pages/tolastloc.png" alt="'.$alttext.'" class="LC_icon" />',
                             { href => '/adm/flip?postdata=return:',
-                              title => &mt("Back to most recent content resource") });
+                              title => &mt('Back to most recent content resource'),
+                              class => 'LC_menubuttons_link',
+                            });
             $links=&htmltag('li',$links);
         }
         $links.= join "", 
@@ -1649,8 +1710,10 @@ returns: nothing
         # 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});
+        if ($lasttext ne '') {
+            $links .= &htmltag( 'li', htmltag($CourseBreadcrumbs ? 'b' : 'h1',
+                    $lasttext), {title => $lasttext});
+        }
 
         my $icons = '';
         $faq  = $last->{'faq'}  if (exists($last->{'faq'}));
@@ -1671,11 +1734,12 @@ returns: nothing
         #
 
 		
-
-        unless ($CourseBreadcrumbs) {
-            $links = &htmltag('ol',  $links, { id => "LC_MenuBreadcrumbs"   });
-        } else {
-            $links = &htmltag('ul',  $links, { class => "LC_CourseBreadcrumbs" });
+        if ($links ne '') {
+            unless ($CourseBreadcrumbs) {
+                $links = &htmltag('ol',  $links, { id => "LC_MenuBreadcrumbs"   });
+            } else {
+                $links = &htmltag('ul',  $links, { class => "LC_CourseBreadcrumbs" });
+            }
         }
 
 
@@ -1819,6 +1883,80 @@ returns: nothing
 
 } # End of scope for @Crumbs
 
+sub docs_breadcrumbs {
+    my ($allowed,$crstype,$contenteditor,$title,$precleared)=@_;
+    my ($folderpath,@folders);
+    if ($env{'form.pagepath'}) {
+        @folders = split('&',$env{'form.pagepath'});
+    } else {
+        @folders = split('&',$env{'form.folderpath'});
+    }
+    my $plain='';
+    my ($randompick,$isencrypted,$ishidden,$is_random_order) = (-1,0,0,0);
+    my @docs_crumbs;
+    while (@folders) {
+        my $folder=shift(@folders);
+        my $foldername=shift(@folders);
+        if ($folderpath) {$folderpath.='&';}
+        $folderpath.=$folder.'&'.$foldername;
+        my $url;
+        if ($allowed) {
+            $url = '/adm/coursedocs?folderpath=';
+        } else {
+            $url = '/adm/supplemental?folderpath=';
+        }
+        $url .= &escape($folderpath);
+        my $name=&unescape($foldername);
+# each of randompick number, hidden, encrypted, random order are 
+# appended with ":"s to the foldername
+        $name=~s/\:(\d*)\:(\w*)\:(\w*):(\d*)$//;
+        if ($contenteditor) { 
+            if ($1 ne '') {
+                $randompick=$1;
+            } else {
+               $randompick=-1;
+            }
+            if ($2) { $ishidden=1; }
+            if ($3) { $isencrypted=1; }
+            if ($4 ne '') { $is_random_order = 1; }
+        }
+        if ($folder eq 'supplemental') {
+            $name = &mt('Supplemental '.$crstype.' Contents');
+        }
+        if ($contenteditor) {
+            $plain.=$name.' &gt; ';
+        }
+        push(@docs_crumbs,
+                          {'href'  => $url,
+                           'title' => $name,
+                           'text'  => $name,
+                           'no_mt' => 1,
+                          });
+    }
+    if (wantarray) {
+        unless ($precleared) {
+            &clear_breadcrumbs();
+        }
+        &add_breadcrumb(@docs_crumbs);
+        if ($title) {
+            &add_breadcrumb({text => $title});
+        }
+        if ($contenteditor) {
+            $plain=~s/\&gt\;\s*$//;
+        }
+        my $menulink = 0;
+        if (!$allowed && !$contenteditor) {
+            $menulink = 1;
+        }
+        return (&breadcrumbs(undef,undef,$menulink,'nohelp',undef,undef,
+                             $contenteditor),
+                             $randompick,$ishidden,$isencrypted,$plain,
+                             $is_random_order);
+    } else {
+        return \@docs_crumbs;
+    }
+}
+
 ############################################################
 ############################################################
 
@@ -2873,29 +3011,6 @@ PARAMSONE
         if (itemid.offsetWidth != itemwstart) {
             listwchange = 1;
         }
-THIRD
-    if ($context eq 'docs') {
-        $output .= <<"DOCSTWO";
-        if (activeTab == 'cc1') {
-            if (document.getElementById('cc_hrule') != null) {
-                document.getElementById('cc_hrule').style.width=actabw+"px";
-            }
-        } else {
-            if (activeTab == 'bb1') {
-                if (document.getElementById('bb_hrule') != null) {
-                    document.getElementById('bb_hrule').style.width=actabw+"px";
-                }
-            } else {
-                if (activeTab == 'ee2') {
-                    if (document.getElementById('ee_hrule') != null) {
-                        document.getElementById('ee_hrule').style.width=actabw+"px";
-                    }
-                }
-            }
-        }
-DOCSTWO
-    }
-    $output .= <<"FOURTH";
     }
     if ((chkh == 1) || (listwchange)) {
         var primaryheight = document.getElementById('LC_nav_bar').offsetHeight;
@@ -2955,10 +3070,90 @@ function callResize() {
     timer=setTimeout('resize_scrollbox("$names{'scroll'}","1","1")',500);
 }
 
-FOURTH
+THIRD
     return $output;
 }
 
+##############################################
+##############################################
+
+sub javascript_jumpto_resource {
+    my $confirm_switch = &mt("Editing requires switching to the resource's home server.").'\n'.
+                         &mt('Switch server?');
+    return (<<ENDUTILITY)
+
+function go(url) {
+   if (url!='' && url!= null) {
+       currentURL = null;
+       currentSymb= null;
+       window.location.href=url;
+   }
+}
+
+function need_switchserver(url) {
+    if (url!='' && url!= null) {
+        if (confirm("$confirm_switch")) {
+            go(url);
+        }
+    }
+    return;
+}
+
+ENDUTILITY
+
+}
+
+sub jump_to_editres {
+    my ($cfile,$home,$switchserver,$forceedit,$forcereg,$symb,$folderpath,
+        $title,$idx,$suppurl) = @_;
+    my $jscall;
+    if ($switchserver) {
+        if ($home) {
+            $cfile = '/adm/switchserver?otherserver='.$home.'&amp;role='.
+                     &HTML::Entities::encode($env{'request.role'},'"<>&');
+            if ($symb) {
+                $cfile .= '&amp;symb='.&HTML::Entities::encode($symb,'"<>&');
+            } elsif ($folderpath) {
+                $cfile .= '&amp;folderpath='.&HTML::Entities::encode($folderpath,'"<>&');
+            }
+            if ($forceedit) {
+                $cfile .= '&amp;forceedit=1';
+            }
+            if ($forcereg) {
+                $cfile .= '&amp;register=1';
+            }
+            $jscall = "need_switchserver('$cfile');";
+        }
+    } else {
+        unless ($cfile =~ m{^/priv/}) {
+            if ($symb) {
+                $cfile .= (($cfile=~/\?/)?'&amp;':'?')."symb=$symb";
+            } elsif ($folderpath) {
+                $cfile .= (($cfile=~/\?/)?'&amp;':'?').
+                          'folderpath='.&HTML::Entities::encode(&escape($folderpath),'"<>&');
+                if ($title) {
+                    $cfile .= (($cfile=~/\?/)?'&amp;':'?').
+                              'title='.&HTML::Entities::encode(&escape($title),'"<>&');
+                }
+                if ($idx) {
+                    $cfile .= (($cfile=~/\?/)?'&amp;':'?').'idx='.$idx;
+                }
+                if ($suppurl) {
+                    $cfile .= (($cfile=~/\?/)?'&amp;':'?').
+                              'suppurl='.&HTML::Entities::encode(&escape($suppurl));
+                }
+            }
+            if ($forceedit) {
+                $cfile .= (($cfile=~/\?/)?'&amp;':'?').'forceedit=1';
+            }
+            if ($forcereg) {
+                $cfile .= (($cfile=~/\?/)?'&amp;':'?').'register=1';
+            }
+        }
+        $jscall = "go('$cfile')";
+    }
+    return $jscall;
+}
 
 ##############################################
 ##############################################