Diff for /loncom/interface/lonhtmlcommon.pm between versions 1.253.2.7 and 1.321

version 1.253.2.7, 2010/12/02 13:47:17 version 1.321, 2012/09/04 11:01:54
Line 60  use Time::Local; Line 60  use Time::Local;
 use Time::HiRes;  use Time::HiRes;
 use Apache::lonlocal;  use Apache::lonlocal;
 use Apache::lonnet;  use Apache::lonnet;
   use HTML::Entities();
 use LONCAPA;  use LONCAPA;
   
   sub java_not_enabled {
      return "\n".'<span class="LC_error">'.
             &mt('The required Java applet could not be started. Please make sure to have Java installed and active in your browser.').
             "</span>\n";
   }
   
 sub coursepreflink {  sub coursepreflink {
    my ($text,$category)=@_;     my ($text,$category)=@_;
    if (&Apache::lonnet::allowed('opa',$env{'request.course.id'})) {     if (&Apache::lonnet::allowed('opa',$env{'request.course.id'})) {
       return '<a href="/adm/courseprefs?phase=display&actions='.$category.'">'.$text.'</a>';        return '<a target="_top" href="'.&HTML::Entities::encode("/adm/courseprefs?phase=display&actions=$category",'<>&"').'"><span class="LC_setting">'.$text.'</span></a>';
    } else {     } else {
       return '';        return '';
    }     }
Line 74  sub coursepreflink { Line 80  sub coursepreflink {
   
 sub raw_href_to_link {  sub raw_href_to_link {
    my ($message)=@_;     my ($message)=@_;
    $message=~s/(https?\:\/\/[^\s\'\"]+)(\s|$)/<a href="$1"><tt>$1<\/tt><\/a>$2/gi;     $message=~s/(https?\:\/\/[^\s\'\"\<]+)([\s\<]|$)/<a href="$1"><tt>$1<\/tt><\/a>$2/gi;
    return $message;     return $message;
 }  }
   
   sub entity_encode {
       my ($text)=@_;
       return &HTML::Entities::encode($text, '<>&"');
   }
   
   sub direct_parm_link {
       my ($linktext,$symb,$filter,$part,$target)=@_;
       $symb=&entity_encode($symb);
       $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&amp;filter=$filter&amp;part=$part'><span class='LC_setting'>$linktext</span></a>";
       } else {
          return $linktext;
       }
   }
 ##############################################  ##############################################
 ##############################################  ##############################################
   
 =pod  =item &confirm_success()
   
 =item confirm_success  
   
 Successful completion of an operation message  Successful completion of an operation message
   
Line 92  Successful completion of an operation me Line 112  Successful completion of an operation me
 sub confirm_success {  sub confirm_success {
    my ($message,$failure)=@_;     my ($message,$failure)=@_;
    if ($failure) {     if ($failure) {
       return '<span class="LC_error">'."\n"        return '<span class="LC_error" style="font-size: inherit;">'."\n"
             .'<img src="/adm/lonIcons/navmap.wrong.gif" alt="'.&mt('Error').'" /> '."\n"              .'<img src="/adm/lonIcons/navmap.wrong.gif" alt="'.&mt('Error').'" /> '."\n"
             .$message."\n"              .$message."\n"
             .'</span>'."\n";              .'</span>'."\n";
Line 109  sub confirm_success { Line 129  sub confirm_success {
   
 =pod  =pod
   
 =item dragmath_button  =item &dragmath_button()
   
 Creates a button that launches a dragmath popup-window, in which an   Creates a button that launches a dragmath popup-window, in which an 
 expression can be edited and pasted as LaTeX into a specified textarea.   expression can be edited and pasted as LaTeX into a specified textarea. 
Line 123  sub dragmath_button { Line 143  sub dragmath_button {
     my ($textarea,$helpicon) = @_;      my ($textarea,$helpicon) = @_;
     my $help_text;       my $help_text; 
     if ($helpicon) {      if ($helpicon) {
         $help_text = &Apache::loncommon::help_open_topic('Authoring_Math_Editor');          $help_text = &Apache::loncommon::help_open_topic('Authoring_Math_Editor',undef,undef,undef,undef,'mathhelpicon_'.$textarea);
     }      }
     my $buttontext=&mt('Edit Math');      my $buttontext=&mt('Edit Math');
     return <<ENDDRAGMATH;      return <<ENDDRAGMATH;
Line 135  ENDDRAGMATH Line 155  ENDDRAGMATH
   
 =pod  =pod
   
 =item dragmath_js  =item &dragmath_js()
   
 Javascript used to open pop-up window containing dragmath applet which   Javascript used to open pop-up window containing dragmath applet which 
 can be used to paste LaTeX into a textarea.  can be used to paste LaTeX into a textarea.
    
 =cut  =cut
   
 sub dragmath_js {  sub dragmath_js {
Line 158  sub dragmath_js { Line 178  sub dragmath_js {
 ENDDRAGMATHJS  ENDDRAGMATHJS
 }  }
   
   ##############################################
   ##############################################
   
   =pod
   
   =item &dependencies_button()
   
   Creates a button that launches a popup-window, in which dependencies  
   for the web page in the main window can be added to, replaced or deleted.  
   
   =cut
   
   sub dependencies_button {
       my $buttontext=&mt('Manage Dependencies');
       return <<"END";
                   <input type="button" value="$buttontext" onclick="javascript:dependencycheck();" />
   END
   }
   
   ##############################################
   
   =pod
   
   =item &dependencycheck_js()
   
   Javascript used to open pop-up window containing interface to manage 
   dependencies for a web page uploaded diretcly to a course.
   
   =cut
   
   sub dependencycheck_js {
       my ($symb,$title,$url) = @_;
       my $link = '/adm/dependencies?symb='.&HTML::Entities::encode($symb,'<>&"').
                  '&title='.&HTML::Entities::encode($title,'<>&"').
                  '&url='.&HTML::Entities::encode($url,'<>&"');
       return <<ENDJS;
                   <script type="text/javascript">
                   // <![CDATA[
                     function dependencycheck() {
                        depwin  = window.open("$link","","width=750,height=500,resizable,scrollbars=yes");
                     }
                   // ]]>
                   </script>
   ENDJS
   }
   
 ##############################################  ##############################################
 ##############################################  ##############################################
   
 =pod  =pod
   
 =item authorbombs  =item &authorbombs()
   
 =cut  =cut
   
Line 298  sub get_recent_frozen { Line 363  sub get_recent_frozen {
   
 =pod  =pod
   
 =item textbox  =item &textbox()
   
 =cut  =cut
   
Line 318  sub textbox { Line 383  sub textbox {
   
 =pod  =pod
   
 =item checkbox  =item &checkbox()
   
 =cut  =cut
   
Line 340  sub checkbox { Line 405  sub checkbox {
   
 =pod  =pod
   
 =item radiobutton  =item &radiobutton()
   
 =cut  =cut
   
Line 364  sub radio { Line 429  sub radio {
   
 =pod  =pod
   
 =item &date_setter  =item &date_setter()
   
 &date_setter returns html and javascript for a compact date-setting form.  &date_setter returns html and javascript for a compact date-setting form.
 To retrieve values from it, use &get_date_from_form().  To retrieve values from it, use &get_date_from_form.
   
 Inputs  Inputs
   
Line 383  dname_hour, dname_min, and dname_sec. Line 448  dname_hour, dname_min, and dname_sec.
   
 The current setting for this time parameter.  A unix format time  The current setting for this time parameter.  A unix format time
 (time in seconds since the beginning of Jan 1st, 1970, GMT.    (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.  Also, to be explicit, a value of 'now' also indicates the current time.
   
 =item $special  =item $special
Line 393  the date_setter.  See lonparmset for exa Line 459  the date_setter.  See lonparmset for exa
   
 =item $includeempty   =item $includeempty 
   
   If it is set (true) and no date/time value is provided,
   the date/time fields are left empty.
   
 =item $state  =item $state
   
 Specifies the initial state of the form elements.  Either 'disabled' or empty.  Specifies the initial state of the form elements.  Either 'disabled' or empty.
Line 410  The method used to restrict user input w Line 479  The method used to restrict user input w
 ##############################################  ##############################################
 sub date_setter {  sub date_setter {
     my ($formname,$dname,$currentvalue,$special,$includeempty,$state,      my ($formname,$dname,$currentvalue,$special,$includeempty,$state,
         $no_hh_mm_ss,$defhour,$defmin,$defsec,$nolink,$hide_timezone) = @_;          $no_hh_mm_ss,$defhour,$defmin,$defsec,$nolink) = @_;
     my $now = time;      my $now = time;
     my $wasdefined=1;  
       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') {      if (! defined($state) || $state ne 'disabled') {
         $state = '';          $state = '';
     }      }
Line 420  sub date_setter { Line 493  sub date_setter {
         $no_hh_mm_ss = 0;          $no_hh_mm_ss = 0;
     }      }
     if ($currentvalue eq 'now') {      if ($currentvalue eq 'now') {
  $currentvalue = $now;          $currentvalue = $now;
     }      }
     if ((!defined($currentvalue)) || ($currentvalue eq '')) {      
  $wasdefined=0;      # Default value: Set empty date field to current time
  if ($includeempty) {      # unless empty inclusion is requested
     $currentvalue = 0;      if ((!$includeempty) && (!$currentvalue)) {
  } else {          $currentvalue = $now;
     $currentvalue = $now;  
  }  
     }      }
     # other potentially useful values:     wkday,yrday,is_daylight_savings      # Do we have a date? Split it!
     my $tzname;  
     my ($sec,$min,$hour,$mday,$month,$year)=('','',undef,'','','');  
     if ($currentvalue) {      if ($currentvalue) {
         ($tzname,$sec,$min,$hour,$mday,$month,$year) = &get_timedates($currentvalue);    ($tzname,$sec,$min,$hour,$mday,$month,$year) = &get_timedates($currentvalue);
     }  
     unless ($wasdefined) {          #No values provided for hour, min, sec? Use default 0
         ($tzname,$sec,$min,$hour,$mday,$month,$year) = &get_timedates($now);          if (($defhour) || ($defmin) || ($defsec)) {
  if (($defhour) || ($defmin) || ($defsec)) {              $sec  = ($defsec  ? $defsec  : 0);
     $sec=($defsec?$defsec:0);              $min  = ($defmin  ? $defmin  : 0);
     $min=($defmin?$defmin:0);              $hour = ($defhour ? $defhour : 0);
     $hour=($defhour?$defhour:0);          }
  } elsif (!$includeempty) {  
     $sec=0;  
     $min=0;  
     $hour=0;  
  }  
     }      }
     my $result = "\n<!-- $dname date setting form -->\n";      my $result = "\n<!-- $dname date setting form -->\n";
     $result .= <<ENDJS;      $result .= <<ENDJS;
Line 563  ENDJS Line 627  ENDJS
         $cal_link = qq{<a href="javascript:$dname\_opencalendar()">};          $cal_link = qq{<a href="javascript:$dname\_opencalendar()">};
     }      }
     #      #
     my $tzone;      my $tzone = ' '.$tzname.' ';
     unless ($hide_timezone) {  
         $tzone = ' '.$tzname.' ';  
     }  
     if ($no_hh_mm_ss) {      if ($no_hh_mm_ss) {
         $result .= &mt('[_1] [_2] [_3] ',          $result .= &mt('[_1] [_2] [_3] ',
                        $monthselector,$dayselector,$yearselector).                         $monthselector,$dayselector,$yearselector).
Line 621  sub build_url { Line 682  sub build_url {
   
 =pod  =pod
   
 =item &get_date_from_form  =item &get_date_from_form()
   
 get_date_from_form retrieves the date specified in an &date_setter form.  get_date_from_form retrieves the date specified in an &date_setter form.
   
Line 646  Returns: Unix time represented in the fo Line 707  Returns: Unix time represented in the fo
 ##############################################  ##############################################
 ##############################################  ##############################################
 sub get_date_from_form {  sub get_date_from_form {
     my ($dname,$timezone) = @_;      my ($dname) = @_;
     my ($sec,$min,$hour,$day,$month,$year);      my ($sec,$min,$hour,$day,$month,$year);
     #      #
     if (defined($env{'form.'.$dname.'_second'})) {      if (defined($env{'form.'.$dname.'_second'})) {
Line 696  sub get_date_from_form { Line 757  sub get_date_from_form {
     if (($year<1970) || ($year>2037)) { return undef; }      if (($year<1970) || ($year>2037)) { return undef; }
     if (defined($sec) && defined($min)   && defined($hour) &&      if (defined($sec) && defined($min)   && defined($hour) &&
         defined($day) && defined($month) && defined($year)) {          defined($day) && defined($month) && defined($year)) {
         if (defined($timezone)) {          my $timezone = &Apache::lonlocal::gettimezone();
             if (&Apache::lonlocal::gettimezone($timezone) eq 'local') {  
                 $timezone = &Apache::lonlocal::gettimezone();  
             }  
         } else {  
             $timezone = &Apache::lonlocal::gettimezone();  
         }  
         my $dt = DateTime->new( year   => $year,          my $dt = DateTime->new( year   => $year,
                                 month  => $month,                                  month  => $month,
                                 day    => $day,                                  day    => $day,
Line 739  parameter setting wizard. Line 794  parameter setting wizard.
 sub pjump_javascript_definition {  sub pjump_javascript_definition {
     my $Str = <<END;      my $Str = <<END;
     function pjump(type,dis,value,marker,ret,call,hour,min,sec) {      function pjump(type,dis,value,marker,ret,call,hour,min,sec) {
         parmwin=window.open("/adm/rat/parameter.html?type="+escape(type)          openMyModal("/adm/rat/parameter.html?type="+escape(type)
                  +"&value="+escape(value)+"&marker="+escape(marker)                   +"&value="+escape(value)+"&marker="+escape(marker)
                  +"&return="+escape(ret)                   +"&return="+escape(ret)
                  +"&call="+escape(call)+"&name="+escape(dis)                   +"&call="+escape(call)+"&name="+escape(dis)
                  +"&defhour="+escape(hour)+"&defmin="+escape(min)                   +"&defhour="+escape(hour)+"&defmin="+escape(min)
                  +"&defsec="+escape(sec),"LONCAPAparms",                   +"&defsec="+escape(sec)+"&modal=1",350,350,'no');
                  "height=350,width=350,scrollbars=no,menubar=no");  
     }      }
 END  END
     return $Str;      return $Str;
Line 887  of items completed and an estimate of th Line 941  of items completed and an estimate of th
 =over 4  =over 4
   
   
 =item &Create_PrgWin  =item &Create_PrgWin()
   
 Writes javascript to the client to open a progress window and returns a  Writes javascript to the client to open a progress window and returns a
 data structure used for bookkeeping.  data structure used for bookkeeping.
Line 898  Inputs Line 952  Inputs
   
 =item $r Apache request  =item $r Apache request
   
 =item $title The title of the progress window  
   
 =item $heading A description (usually 1 line) of the process being initiated.  
   
 =item $number_to_do The total number of items being processed.  =item $number_to_do The total number of items being processed.
   
 =item $type Either 'popup' or 'inline' (popup is assumed if nothing is  
        specified)  
   
 =item $width Specify the width in charaters of the input field.  
   
 =item $formname Only useful in the inline case, if a form already exists, this needs to be used and specfiy the name of the form, otherwise the Progress line will be created in a new form of it's own  
   
 =item $inputname Only useful in the inline case, if a form and an input of type text exists, use this to specify the name of the input field   
   
 =back  =back
   
 Returns a hash containing the progress state data structure.  Returns a hash containing the progress state data structure.
   
   
 =item &Update_PrgWin  =item &Update_PrgWin()
   
 Updates the text in the progress indicator.  Does not increment the count.  Updates the text in the progress indicator.  Does not increment the count.
 See &Increment_PrgWin.  See &Increment_PrgWin.
Line 938  Inputs: Line 979  Inputs:
 Returns: none  Returns: none
   
   
 =item Increment_PrgWin  =item Increment_PrgWin()
   
 Increment the count of items completed for the progress window by 1.    Increment the count of items completed for the progress window by $step or 1 if no step is provided.
   
 Inputs:  Inputs:
   
Line 953  Inputs: Line 994  Inputs:
 =item $extraInfo A description of the items being iterated over.  Typically  =item $extraInfo A description of the items being iterated over.  Typically
 'student'.  'student'.
   
   =item $step (optional) counter step. Will be set to default 1 if ommited. step must be greater than 0 or empty.
   
 =back  =back
   
 Returns: none  Returns: none
   
   
 =item Close_PrgWin  =item &Close_PrgWin()
   
 Closes the progress window.  Closes the progress window.
   
Line 981  Returns: none Line 1024  Returns: none
 ########################################################  ########################################################
 ########################################################  ########################################################
   
 my $uniq=0;  
 sub get_uniq_name {  
     $uniq++;  
     return 'uniquename'.$uniq;  
 }  
   
 # Create progress  # Create progress
 sub Create_PrgWin {  sub Create_PrgWin {
     my ($r, $title, $heading, $number_to_do,$type,$width,$formname,      my ($r,$number_to_do)=@_;
  $inputname)=@_;  
     if (!defined($type)) { $type='popup'; }  
     if (!defined($width)) { $width=55; }  
     my %prog_state;      my %prog_state;
     $prog_state{'type'}=$type;  
     if ($type eq 'popup') {  
  $prog_state{'window'}='popwin';  
  my $start_page =  
     &Apache::loncommon::start_page($title,undef,  
    {'only_body' => 1,  
     'bgcolor'   => '#88DDFF',  
     'js_ready'  => 1});  
  my $end_page = &Apache::loncommon::end_page({'js_ready'  => 1});  
   
  #the whole function called through timeout is due to issues  
  #in mozilla Read BUG #2665 if you want to know the whole story  
  &r_print($r,&Apache::lonhtmlcommon::scripttag(  
         "var popwin;  
          function openpopwin () {  
          popwin=open(\'\',\'popwin\',\'width=400,height=100\');".  
         "popwin.document.writeln(\'".$start_page.  
               "<h4>".&mt("$heading")."<\/h4>".  
               "<form action=\"\" name=\"popremain\" method=\"post\">".  
               '<input type="text" size="'.$width.'" name="remaining" value="'.  
       &mt('Starting').'" /><\\/form>'.$end_page.  
               "\');".  
         "popwin.document.close();}".  
         "\nwindow.setTimeout(openpopwin,0)"  
     ));  
  $prog_state{'formname'}='popremain';  
  $prog_state{'inputname'}="remaining";  
     } elsif ($type eq 'inline') {  
  $prog_state{'window'}='window';  
  if (!$formname) {  
     $prog_state{'formname'}=&get_uniq_name();  
     &r_print($r,'<form action="" name="'.$prog_state{'formname'}.'">');  
  } else {  
     $prog_state{'formname'}=$formname;  
  }  
  if (!$inputname) {  
     $prog_state{'inputname'}=&get_uniq_name();  
     &r_print($r,&mt("$heading [_1]",' <input type="text" name="'.$prog_state{'inputname'}.'" size="'.$width.'" />'));  
  } else {  
     $prog_state{'inputname'}=$inputname;  
       
  }  
  if (!$formname) { &r_print($r,'</form>'); }  
  &Update_PrgWin($r,\%prog_state,&mt('Starting'));  
     }  
   
     $prog_state{'done'}=0;      $prog_state{'done'}=0;
     $prog_state{'firststart'}=&Time::HiRes::time();      $prog_state{'firststart'}=&Time::HiRes::time();
     $prog_state{'laststart'}=&Time::HiRes::time();      $prog_state{'laststart'}=&Time::HiRes::time();
     $prog_state{'max'}=$number_to_do;      $prog_state{'max'}=$number_to_do;
           &Apache::loncommon::LCprogressbar($r); 
     return %prog_state;      return %prog_state;
 }  }
   
 # update progress  # update progress
 sub Update_PrgWin {  sub Update_PrgWin {
     my ($r,$prog_state,$displayString)=@_;      my ($r,$prog_state,$displayString)=@_;
     &r_print($r,&Apache::lonhtmlcommon::scripttag(      &Apache::loncommon::LCprogressbarUpdate($r,undef,$displayString);
         $$prog_state{'window'}.'.document.'.  
         $$prog_state{'formname'}.'.'.  
         $$prog_state{'inputname'}.'.value="'.  
         $displayString.'";'  
     ));  
     $$prog_state{'laststart'}=&Time::HiRes::time();      $$prog_state{'laststart'}=&Time::HiRes::time();
 }  }
   
 # increment progress state  # increment progress state
 sub Increment_PrgWin {  sub Increment_PrgWin {
     my ($r,$prog_state,$extraInfo)=@_;      my ($r,$prog_state,$extraInfo,$step)=@_;
     $$prog_state{'done'}++;      $step = $step > 0 ? $step : 1;
       $$prog_state{'done'} += $step;
   
       # Catch (max modulo step) <> 0
       my $current = $$prog_state{'done'};
       my $last = ($$prog_state{'max'} - $current);
       if ($last <= 0) {
           $last = 1;
           $current = $$prog_state{'max'};
       }
   
     my $time_est= (&Time::HiRes::time() - $$prog_state{'firststart'})/      my $time_est= (&Time::HiRes::time() - $$prog_state{'firststart'})/
         $$prog_state{'done'} *          $current * $last;
  ($$prog_state{'max'}-$$prog_state{'done'});  
     $time_est = int($time_est);      $time_est = int($time_est);
     #      #
     my $min = int($time_est/60);      my $min = int($time_est/60);
     my $sec = $time_est % 60;      my $sec = $time_est % 60;
     #   
     my $str;  
     if ($min == 0 && $sec > 1) {  
         $str = '[_2] seconds';  
     } elsif ($min == 1 && $sec > 1) {  
         $str = '1 minute [_2] seconds';  
     } elsif ($min == 1 && $sec < 2) {  
         $str = '1 minute';  
     } elsif ($min < 10 && $sec > 1) {  
         $str = '[_1] minutes, [_2] seconds';  
     } elsif ($min >= 10 || $sec < 2) {  
         $str = '[_1] minutes';  
     }  
     $time_est = &mt($str,$min,$sec);  
     #  
     my $lasttime = &Time::HiRes::time()-$$prog_state{'laststart'};      my $lasttime = &Time::HiRes::time()-$$prog_state{'laststart'};
     if ($lasttime > 9) {      if ($lasttime > 9) {
         $lasttime = int($lasttime);          $lasttime = int($lasttime);
Line 1094  sub Increment_PrgWin { Line 1073  sub Increment_PrgWin {
     } else {      } else {
         $lasttime = sprintf("%3.2f",$lasttime);          $lasttime = sprintf("%3.2f",$lasttime);
     }      }
     if ($lasttime == 1) {  
         $lasttime = '('.$lasttime.' '.&mt('second for').' '.$extraInfo.')';      $sec = 0 if ($min >= 10); # Don't show seconds if remaining time >= 10 min.
     } else {      $sec = 1 if ( ($min == 0) && ($sec == 0) ); # Little cheating: pretend to have 1 second remaining instead of 0 to have something to display
         $lasttime = '('.$lasttime.' '.&mt('seconds for').' '.$extraInfo.')';  
     }      my $timeinfo =
     #          &mt('[_1]/[_2]:'
     my $user_browser = $env{'browser.type'} if (exists($env{'browser.type'}));             .' [quant,_3,minute,minutes,] [quant,_4,second ,seconds ,]remaining'
     my $user_os      = $env{'browser.os'}   if (exists($env{'browser.os'}));             .' ([quant,_5,second] for '.$extraInfo.')',
     if (! defined($user_browser) || ! defined($user_os)) {              $current,
         (undef,$user_browser,undef,undef,undef,$user_os) =               $$prog_state{'max'},
                            &Apache::loncommon::decode_user_agent();              $min,
     }              $sec,
     if ($user_browser eq 'explorer' && $user_os =~ 'mac') {              $lasttime);
         $lasttime = '';      my $percent=0;
       if ($$prog_state{'max'}) {
          $percent=int(100.*$current/$$prog_state{'max'});
     }      }
     &r_print($r,&Apache::lonhtmlcommon::scripttag(      &Apache::loncommon::LCprogressbarUpdate($r,$percent,$timeinfo);
         $$prog_state{'window'}.'.document.'.  
         $$prog_state{'formname'}.'.'.  
         $$prog_state{'inputname'}.'.value="'.  
         $$prog_state{'done'}.'/'.$$prog_state{'max'}.  
         ': '.$time_est.' '.&mt('remaining').' '.$lasttime.'";'  
     ));  
     $$prog_state{'laststart'}=&Time::HiRes::time();      $$prog_state{'laststart'}=&Time::HiRes::time();
 }  }
   
 # close Progress Line  # close Progress Line
 sub Close_PrgWin {  sub Close_PrgWin {
     my ($r,$prog_state)=@_;      my ($r,$prog_state)=@_;
     if ($$prog_state{'type'} eq 'popup') {      &Apache::loncommon::LCprogressbarClose($r);
         &r_print($r,&Apache::lonhtmlcommon::scripttag(  
             'popwin.close()'  
         ));  
     } elsif ($$prog_state{'type'} eq 'inline') {  
  &Update_PrgWin($r,$prog_state,&mt('Done'));  
     }  
     undef(%$prog_state);      undef(%$prog_state);
 }  }
   
 sub r_print {  
     my ($r,$to_print)=@_;  
     if ($r) {  
  $r->print($to_print);  
  $r->rflush();  
     } else {  
  print($to_print);  
     }  
 }  
   
 # ------------------------------------------------------- Puts directory header  # ------------------------------------------------------- Puts directory header
   
 sub crumbs {  sub crumbs {
     my ($uri,$target,$prefix,$form,$skiplast)=@_;      my ($uri,$target,$prefix,$form,$skiplast)=@_;
   # You cannot crumbnify uploaded or adm resources
       if ($uri=~/^\/*(uploaded|adm)\//) { return &mt('(Internal Course/Group Content)'); }
     if ($target) {      if ($target) {
         $target = ' target="'.          $target = ' target="'.
                   &Apache::loncommon::escape_single($target).'"';                    &Apache::loncommon::escape_single($target).'"';
Line 1183  sub crumbs { Line 1144  sub crumbs {
     if ($uri !~ m|/$|) { $output=~s|/$||; }      if ($uri !~ m|/$|) { $output=~s|/$||; }
     $output.='</span>';      $output.='</span>';
   
   
     return $output;      return $output;
 }  }
   
Line 1231  sub spelllink { Line 1193  sub spelllink {
 ENDLINK  ENDLINK
 }  }
   
 # ------------------------------------------------- Output headers for HTMLArea  # ------------------------------------------------- Output headers for CKEditor
   
 {  
     my @htmlareafields;  
     sub init_htmlareafields {  
  undef(@htmlareafields);  
     }  
       
     sub add_htmlareafields {  
  my (@newfields) = @_;  
  push(@htmlareafields,@newfields);  
     }  
   
     sub get_htmlareafields {  
  return @htmlareafields;  
     }  
 }  
   
 sub htmlareaheaders {  sub htmlareaheaders {
     return if (&htmlareablocked());   my $s="";
     return if (!&htmlareabrowser());   if (&htmlareabrowser()) {
     return (<<ENDHEADERS);   $s.=(<<ENDEDITOR);
 <script type="text/javascript" src="/fckeditor/fckeditor.js"></script>  <script type="text/javascript" src="/ckeditor/ckeditor.js"></script>
 ENDHEADERS  ENDEDITOR
 }   }
       $s.=(<<ENDJQUERY);
   <script type="text/javascript" src="/adm/jQuery/js/jquery-1.6.2.min.js"></script>
   <script type="text/javascript" src="/adm/jQuery/js/jquery-ui-1.8.16.custom.min.js"></script>
   <link rel="stylesheet" type="text/css" href="/adm/jQuery/css/smoothness/jquery-ui-1.8.16.custom.css" />
   <script type="text/javascript" src="/adm/jpicker/js/jpicker-1.1.6.min.js" >
   </script>
   <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" />
   
 # ----------------------------------------------------------------- Preferences  <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" />
   
 sub disablelink {  ENDJQUERY
     my @fields=@_;   return $s;
     if (defined($#fields)) {  
  unless ($#fields>=0) { return ''; }  
     }  
     return '<a href="'.&HTML::Entities::encode('/adm/preferences?action=set_wysiwyg&wysiwyg=off&returnurl=','<>&"').&escape($ENV{'REQUEST_URI'}).'">'.&mt('Disable WYSIWYG Editor').'</a>';  
 }  }
   
 sub enablelink {  # ----------------------------------------------------------------- Preferences
     my @fields=@_;  
     if (defined($#fields)) {  
  unless ($#fields>=0) { return ''; }  
     }  
     return '<a href="'.&HTML::Entities::encode('/adm/preferences?action=set_wysiwyg&wysiwyg=on&returnurl=','<>&"').&escape($ENV{'REQUEST_URI'}).'">'.&mt('Enable WYSIWYG Editor').'</a>';  
 }  
   
 # ------------------------------------------------- lang to use in html editor  # ------------------------------------------------- lang to use in html editor
 sub htmlarea_lang {  sub htmlarea_lang {
Line 1287  sub htmlarea_lang { Line 1233  sub htmlarea_lang {
 # ----------------------------------------- Script to activate only some fields  # ----------------------------------------- Script to activate only some fields
   
 sub htmlareaselectactive {  sub htmlareaselectactive {
     my @fields=@_;      my ($args) = @_; 
     unless (&htmlareabrowser()) { return ''; }      unless (&htmlareabrowser()) { return ''; }
     if (&htmlareablocked()) { return '<br />'.&enablelink(@fields); }      my $output='<script type="text/javascript" defer="defer">'."\n"
     my $output='<script type="text/javascript" defer="1">'."\n"  
               .'// <![CDATA['."\n";                .'// <![CDATA['."\n";
     my $lang = &htmlarea_lang();      my $lang = &htmlarea_lang();
     foreach my $field (@fields) {      my $fullpage = 'false';
  $output.="      my ($dragmath_prefix,$dragmath_helpicon,$dragmath_whitespace);
 {      if (ref($args) eq 'HASH') {
     var oFCKeditor = new FCKeditor('$field');          if (exists($args->{'lang'})) {
     oFCKeditor.Config['CustomConfigurationsPath'] =               if ($args->{'lang'} ne '') {
  '/fckeditor/loncapaconfig.js';                      $lang = $args->{'lang'};
     oFCKeditor.ReplaceTextarea();              }
     oFCKeditor.Config['AutoDetectLanguage'] = false;          }
     oFCKeditor.Config['DefaultLanguage'] = '$lang';          if (exists($args->{'fullpage'})) { 
 }";              if ($args->{'fullpage'} eq 'true') {
                   $fullpage = $args->{'fullpage'};
               }
           }
           if (exists($args->{'dragmath'})) {
               if ($args->{'dragmath'} ne '') {
                   $dragmath_prefix = $args->{'dragmath'};
                   $dragmath_helpicon=&Apache::loncommon::lonhttpdurl("/adm/help/help.png");
                   $dragmath_whitespace=&Apache::loncommon::lonhttpdurl("/adm/lonIcons/transparent1x1.gif");
               }
           }
       }
       $output.='
       
       function containsBlockHtml(id) {
    var re = $("#"+id).html().search(/(?:\&lt\;|\<)(br|h1|h2|h3|h4|h5|h6|p|ol|ul|table|pre|address|blockquote|center|div)[\s]*((?:[\/]*[\s]*(?:\&gt\;|\>)|(?:\&gt\;|\>)[\s\S]*(?:\&lt\;|\<)\/[\s]*\1[\s]*\(?:\&gt\;|\>))/im);
       return (re >= 0);
       }
       
       function startRichEditor(id) {
       CKEDITOR.replace(id, 
       {
       customConfig: "/ckeditor/loncapaconfig.js",
                           language : "'.$lang.'",
                           fullPage : '.$fullpage.',
       }
       );
       }
       
       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();
       var rt_enabled  = $(this).hasClass("LC_enable_rt");
           if (rt_enabled) {
       startRichEditor(id);
    $("#LC_rt_"+id).html("<b>&laquo; Plain text</b>");
    $("#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("<b>Rich formatting &raquo;</b>");
    $("#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");
    }';
       if ($dragmath_prefix ne '') {
           $output .= "\n                 var visible = '';
                                          if (rt_enabled) {
                                              visible = 'none';
                                          }
                                          editmath_visibility(id,visible);\n";
       }
       $output .= '
       }
       $(document).ready(function(){
    $(".LC_richAlwaysOn").each(function() {
    startRichEditor($(this).attr("id"));
    });
    $(".LC_richDetectHtml").each(function() {
    var id = $(this).attr("id");
                           var rt_enabled = containsBlockHtml(id);
    if(rt_enabled) {
    $(this).before("<div><a href=\"#\" id=\"LC_rt_"+id+"\" title=\"Disable rich text formatting and edit in plain text\" class=\"LC_disable_rt\"><b>&laquo; Plain text</b></a></div>");
    startRichEditor(id);
    $("#LC_rt_"+id).click(editorHandler);
    }
    else {
    $(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);
    }';
       if ($dragmath_prefix ne '') {
           $output .= "\n                 var visible = '';
                                          if (rt_enabled) {
                                              visible = 'none';
                                          }
                                          editmath_visibility(id,visible);\n";
       }
       $output .= '
    });
    $(".LC_richDefaultOn").each(function() {
    var id = $(this).attr("id");
    $(this).before("<div><a href=\"#\" id=\"LC_rt_"+id+"\" title=\"Disable rich text formatting and edit in plain text\" class=\"LC_disable_rt\"><b>&laquo; Plain text</b></a></div>");
    startRichEditor(id);
    $("#LC_rt_"+id).click(editorHandler);
    });
    $(".LC_richDefaultOff").each(function() {
    var id = $(this).attr("id");
    $(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();
   
   
    });
   ';
       # 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]',"<span id='submitearly'></span>");
       my $early = '- <b>'.&mt('Submit Early').'</b>';
       my $pastdue = '- <b>'.&mt('Past Due').'</b>';
       $output .= <<JAVASCRIPT;
   
       var documentReadyTime;
   
   \$(document).ready(function() {
      if (typeof(dueDate) != "undefined") {
          documentReadyTime = (new Date()).getTime();
         \$("#duedatecountdown").countdown({until: dueDate, compact: true, 
            layout: "$dueDateLayout",
            onTick: function (periods) {
       var latencyEstimate = (documentReadyTime - clientTime) * 2;
               if(\$.countdown.periodsToSeconds(periods) < (300 + latencyEstimate)) {
                  \$("#submitearly").html("$early");
                  if (\$.countdown.periodsToSeconds(periods) < 1) {
                       \$("#submitearly").html("$pastdue");
                  }
               }
               if(\$.countdown.periodsToSeconds(periods) < (60 + latencyEstimate)) {
                  \$(this).css("color", "red");   //Highlight last minute.
               }
            }
         });
      }
   });
   JAVASCRIPT
       if ($dragmath_prefix ne '') {
           $output .= '
   
        function editmath_visibility(id,value) {
   
            if ((id == "") || (id == null)) {
                return;
            }
            var mathid = "'.$dragmath_prefix.'_"+id;
            mathele = document.getElementById(mathid);
            if (mathele == null) {
                return;
            }
            mathele.style.display = value;
            var mathhelpicon = "'.$dragmath_prefix.'helpicon'.'_"+id;
            mathhelpiconele = document.getElementById(mathhelpicon);
            if (mathhelpiconele == null) {
                return;
            }
            if (value == "none") {
                mathhelpiconele.src = "'.$dragmath_whitespace.'";
            } else {
                mathhelpiconele.src = "'.$dragmath_helpicon.'";
            }
        }
   ';
   
     }      }
     $output.="\nwindow.status='Activated Editfields';\n"      $output.="\nwindow.status='Activated Editfields';\n"
             .'// ]]>'."\n"              .'// ]]>'."\n"
             .'</script><br />'.              .'</script>';
  &disablelink(@fields);  
     return $output;      return $output;
 }  }
   
Line 1324  sub htmlareabrowser { Line 1450  sub htmlareabrowser {
     return 1;      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";
   
   <script type="text/javascript">
     //<![CDATA[
   var serverDueDate = $duems;
   var serverTime    = $now;
   var clientTime    = (new Date()).getTime();
   var dueDate       = new Date(serverDueDate + (clientTime - serverTime));
   
     //]]>
   </script>
   
   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";
   
   <script type="text/javascript">
   //<![CDATA[
   serverTime = $now;
   clientTime = (new Date()).getTime();
   //]]>
   </script>
   
   END
   }
   
 ############################################################  ############################################################
 ############################################################  ############################################################
   
 =pod  =pod
   
 =item breadcrumbs  =item &breadcrumbs()
   
 Compiles the previously registered breadcrumbs into an series of links.  Compiles the previously registered breadcrumbs into an series of links.
 Additionally supports a 'component', which will be displayed on the  Additionally supports a 'component', which will be displayed on the
Line 1347  Inputs: $component (the text on the righ Line 1556  Inputs: $component (the text on the righ
            when including the text on the right.             when including the text on the right.
 Returns a string containing breadcrumbs for the current page.  Returns a string containing breadcrumbs for the current page.
   
 =item clear_breadcrumbs  =item &clear_breadcrumbs()
   
 Clears the previously stored breadcrumbs.  Clears the previously stored breadcrumbs.
   
 =item add_breadcrumb  =item &add_breadcrumb()
   
 Pushes a breadcrumb on the stack of crumbs.  Pushes a breadcrumb on the stack of crumbs.
   
Line 1371  returns: nothing Line 1580  returns: nothing
     my %tools = ();      my %tools = ();
           
     sub breadcrumbs {      sub breadcrumbs {
         my ($component,$component_help,$menulink,$helplink,$css_class,$no_mt, $CourseBreadcrumbs) = @_;          my ($component,$component_help,$menulink,$helplink,$css_class,$no_mt, 
               $CourseBreadcrumbs) = @_;
         #          #
         $css_class ||= 'LC_breadcrumbs';          $css_class ||= 'LC_breadcrumbs';
   
Line 1387  returns: nothing Line 1597  returns: nothing
         # The first one should be the course or a menu link          # The first one should be the course or a menu link
         if (!defined($menulink)) { $menulink=1; }          if (!defined($menulink)) { $menulink=1; }
         if ($menulink) {          if ($menulink) {
             if ($menulink eq '_nomenu') {              my $description = 'Menu';
                 return unless($last);              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;
               }
               $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 {              } else {
                 my $description = 'Menu';                  #only menulink crumb present
                 my $href = '/adm/menu';                  $last = $menulink;
                 my $tooltip = 'Go to main menu';  
                 my $no_mt_descr = 0;  
                 if ((exists($env{'request.course.id'})) &&  
                     ($env{'request.course.id'} ne '') &&   
                     !($env{'form.context'} eq 'requestcrs')) {  
                     if ((&Apache::loncommon::needs_gci_custom()) || ($env{'user.domain'} eq 'gcitest')) {  
                         if ($env{'environment.remotenavmap'} eq 'on') {  
                             # open link using javascript when remote navmap is activated  
                             $href = "javascript:gonav('/adm/navmaps');";  
                         } else {  
                             $href = '/adm/navmaps';  
                         }  
                         $tooltip = 'Contents';  
                     }  
                     if ($env{'course.'.$env{'request.course.id'}.'.description'} ne '') {  
                         $description =  
                             $env{'course.'.$env{'request.course.id'}.'.description'};  
                         $no_mt_descr = 1;  
                     }  
                 }  
                 $menulink =  {  href   => $href,  
                                 title  => $tooltip,  
                                 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 "",           my $links;
                  map {          if ((&show_return_link) && (!$CourseBreadcrumbs)) {
                      $faq  = $_->{'faq'}  if (exists($_->{'faq'}));              my $alttext = &mt('Go Back');
                      $bug  = $_->{'bug'}  if (exists($_->{'bug'}));              $links=&htmltag( 'a','<img src="/res/adm/pages/tolastloc.png" alt="'.$alttext.'" class="LC_icon" />',
                      $help = $_->{'help'} if (exists($_->{'help'}));                              { href => '/adm/flip?postdata=return:',
                                 title => &mt('Back to most recent content resource'),
                      my $result = $_->{no_mt} ? $_->{text} : mt($_->{text});                                class => 'LC_menubuttons_link',
                               });
                      if ($_->{href}){              $links=&htmltag('li',$links);
                          $result = htmltag( 'a', $result,           }
                                            {           $links.= join "", 
                                                href   => $_->{href},               map {
                                                title  => $_->{no_mt} ?                    $faq  = $_->{'faq'}  if (exists($_->{'faq'}));
                                                 $_->{title} : mt($_->{title}),                   $bug  = $_->{'bug'}  if (exists($_->{'bug'}));
                                                target => $_->{target},                   $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");                   $result = &htmltag( 'li', "$result $crumbsymbol");
                  } @Crumbs;               } @Crumbs;
   
         #should the last Element be translated?          #should the last Element be translated?
   
         my $lasttext = $last->{'no_mt'} ? $last->{'text'}          my $lasttext = $last->{'no_mt'} ? $last->{'text'} 
                      : mt( $last->{'text'} );                       : mt( $last->{'text'} );
   
         # last breadcrumb is the first order heading of a page          # last breadcrumb is the first order heading of a page
         # for course breadcrumbs it's just bold          # for course breadcrumbs it's just bold
         $links .= htmltag( 'li', htmltag($CourseBreadcrumbs ? 'b' : 'h1',  
                            $lasttext), {title => $lasttext});          $links .= &htmltag( 'li', htmltag($CourseBreadcrumbs ? 'b' : 'h1',
                   $lasttext), {title => $lasttext});
   
         my $icons = '';          my $icons = '';
         $faq  = $last->{'faq'}  if (exists($last->{'faq'}));          $faq  = $last->{'faq'}  if (exists($last->{'faq'}));
Line 1474  returns: nothing Line 1675  returns: nothing
                                                          $faq,$bug);                                                           $faq,$bug);
         }          }
         #          #
   
   
   
         unless ($CourseBreadcrumbs) {          unless ($CourseBreadcrumbs) {
             $links = htmltag('ol',  $links, { id => "LC_MenuBreadcrumbs"   });              $links = &htmltag('ol',  $links, { id => "LC_MenuBreadcrumbs"   });
         } else {          } else {
             $links = htmltag('ul',  $links, { class => "LC_CourseBreadcrumbs" });              $links = &htmltag('ul',  $links, { class => "LC_CourseBreadcrumbs" });
         }          }
   
   
         if ($component) {          if ($component) {
             $links = htmltag('span',               $links = &htmltag('span', 
                              ( $no_mt ? $component : mt($component) ).                               ( $no_mt ? $component : mt($component) ).
                              ( $icons ? $icons : '' ),                               ( $icons ? $icons : '' ),
                              { class => 'LC_breadcrumbs_component' } )                               { class => 'LC_breadcrumbs_component' } )
                              .$links;                               .$links 
   ;
         }          }
                   
         render_tools(\$links);          &render_tools(\$links);
         $links = htmltag('div', $links,           $links = &htmltag('div', $links, 
                         { id => "LC_breadcrumbs" }) unless ($CourseBreadcrumbs) ;                          { id => "LC_breadcrumbs" }) unless ($CourseBreadcrumbs) ;
         render_advtools(\$links);          &render_advtools(\$links);
   
         # Return the @Crumbs stack to what we started with          # Return the @Crumbs stack to what we started with
         push(@Crumbs,$last);          push(@Crumbs,$last);
         shift(@Crumbs);          shift(@Crumbs);
   
   
         # Return the breadcrumb's line          # Return the breadcrumb's line
   
       
   
         return "$links";          return "$links";
     }      }
   
Line 1511  returns: nothing Line 1720  returns: nothing
         push(@Crumbs,@_);          push(@Crumbs,@_);
     }      }
           
 =item add_breadcrumb_tool($category, $html)  =item &add_breadcrumb_tool($category, $html)
   
 Adds $html to $category of the breadcrumb toolbar container.  Adds $html to $category of the breadcrumb toolbar container.
   
 $html is usually a link to a page that invokes a function on the currently  $html is usually a link to a page that invokes a function on the currently 
 displayed data (e.g. print when viewing a problem)  displayed data (e.g. print when viewing a problem)
   
 Currently there are 3 possible values for $category:  Currently there are 3 possible values for $category: 
   
 =over  =over 
   
 =item navigation  =item navigation 
 left of breadcrumbs line  left of breadcrumbs line
   
 =item tools  =item tools 
 right of breadcrumbs line  remaining items in right of breadcrumbs line
   
 =item advtools  =item advtools 
 advanced tools shown in a separate box below breadcrumbs line  advanced tools shown in a separate box below breadcrumbs line 
   
 =back  =back
    
 returns: nothing  returns: nothing
   
 =cut  =cut
Line 1540  returns: nothing Line 1749  returns: nothing
     sub add_breadcrumb_tool {      sub add_breadcrumb_tool {
         my ($category, @html) = @_;          my ($category, @html) = @_;
         return unless @html;          return unless @html;
         if (!defined(%tools)) {          if (!keys(%tools)) { 
             %tools = ( navigation => [], tools => [], advtools => []);              %tools = ( navigation => [], tools => [], advtools => []);
         }          }
   
         #this cleans data received from lonmenu::innerregister          #this cleans data received from lonmenu::innerregister
         @html = grep {defined $_ && $_ ne ''} @html;          @html = grep {defined $_ && $_ ne ''} @html;
         for (@html) {          for (@html) { 
             s/align="(right|left)"//;              s/align="(right|left)"//; 
             s/<span.*?\/span>// if $category ne 'advtools';  #            s/<span.*?\/span>// if $category ne 'advtools'; 
         }          } 
   
         push @{$tools{$category}}, @html;          push @{$tools{$category}}, @html;
     }      }
   
 =item clear_breadcrumb_tools()  =item &clear_breadcrumb_tools()
   
 Clears the breadcrumb toolbar container.  Clears the breadcrumb toolbar container.
   
Line 1566  returns: nothing Line 1775  returns: nothing
         undef(%tools);          undef(%tools);
     }      }
   
 =item render_tools(\$breadcrumbs)  =item &render_tools(\$breadcrumbs)
   
 Creates html for breadcrumb tools (categories navigation and tools) and inserts  Creates html for breadcrumb tools (categories navigation and tools) and inserts 
 \$breadcrumbs at the correct position.  \$breadcrumbs at the correct position.
   
 input: \$breadcrumbs - a reference to the string containing prepared  input: \$breadcrumbs - a reference to the string containing prepared 
 breadcrumbs.  breadcrumbs.
   
 returns: nothing  returns: nothing
   
 =cut  =cut
   
 #TODO might split this in separate functions for each category  #TODO might split this in separate functions for each category
     sub render_tools {      sub render_tools {
         my ($breadcrumbs) = @_;          my ($breadcrumbs) = @_;
         return unless defined %tools;          return unless (keys(%tools));
   
         my $navigation = list_from_array($tools{navigation},          my $navigation = list_from_array($tools{navigation}, 
                    { listattr => { class=>"LC_breadcrumb_tools_navigation" } });                     { listattr => { class=>"LC_breadcrumb_tools_navigation" } });
         my $tools = list_from_array($tools{tools},          my $tools = list_from_array($tools{tools}, 
                    { listattr => { class=>"LC_breadcrumb_tools_tools" } });                     { listattr => { class=>"LC_breadcrumb_tools_tools" } });
         $$breadcrumbs = list_from_array([$navigation, $tools, $$breadcrumbs],          $$breadcrumbs = list_from_array([$navigation, $tools, $$breadcrumbs], 
                    { listattr => { class=>'LC_breadcrumb_tools_outerlist' } });                     { listattr => { class=>'LC_breadcrumb_tools_outerlist' } });
     }      }
   
 =item render_advtools(\$breadcrumbs,$legend)  =pod
   
   =item &render_advtools(\$breadcrumbs)
   
 Creates html for advanced tools (category advtools) and inserts \$breadcrumbs  Creates html for advanced tools (category advtools) and inserts \$breadcrumbs 
 at the correct position.  at the correct position.
   
 input: \$breadcrumbs - a reference to the string containing prepared  input: \$breadcrumbs - a reference to the string containing prepared 
 breadcrumbs (after render_tools call).  breadcrumbs (after render_tools call).
   
 returns: nothing  returns: nothing
   
 =cut  =cut
   
     sub render_advtools {      sub render_advtools {
         my ($breadcrumbs,$legend) = @_;          my ($breadcrumbs) = @_;
         return unless     (defined $tools{'advtools'})          return unless     (defined $tools{'advtools'}) 
                       and (scalar(@{$tools{'advtools'}}) > 0);                        and (scalar(@{$tools{'advtools'}}) > 0);
         my $args;  
         if ($legend) {  
             $args = {legend => $legend};  
         }  
         $$breadcrumbs .= Apache::loncommon::head_subbox(          $$breadcrumbs .= Apache::loncommon::head_subbox(
                             funclist_from_array($tools{'advtools'},$args));                              funclist_from_array($tools{'advtools'}) );
     }      }
   
 } # End of scope for @Crumbs  } # End of scope for @Crumbs
Line 1675  returns: nothing Line 1885  returns: nothing
 my @row_count;  my @row_count;
   
 sub start_pick_box {  sub start_pick_box {
     my ($css_class) = @_;      my ($css_class,$id) = @_;
     if (defined($css_class)) {      if (defined($css_class)) {
  $css_class = 'class="'.$css_class.'"';   $css_class = 'class="'.$css_class.'"';
     } else {      } else {
  $css_class= 'class="LC_pick_box"';   $css_class= 'class="LC_pick_box"';
     }      }
       my $table_id;
       if (defined($id)) {
           $table_id = ' id="'.$id.'"';
       }
     unshift(@row_count,0);      unshift(@row_count,0);
     my $output = <<"END";      my $output = <<"END";
  <table $css_class>   <table $css_class $table_id>
 END  END
     return $output;      return $output;
 }  }
Line 1789  sub role_select_row { Line 2003  sub role_select_row {
   
 sub course_select_row {  sub course_select_row {
     my ($title,$formname,$totcodes,$codetitles,$idlist,$idlist_titles,      my ($title,$formname,$totcodes,$codetitles,$idlist,$idlist_titles,
  $css_class,$crstype) = @_;   $css_class,$crstype,$standardnames) = @_;
     my $output = &row_title($title,$css_class);      my $output = &row_title($title,$css_class);
     $output .= &course_selection($formname,$totcodes,$codetitles,$idlist,$idlist_titles,$crstype);      $output .= &course_selection($formname,$totcodes,$codetitles,$idlist,$idlist_titles,$crstype,$standardnames);
     $output .= &row_closure();      $output .= &row_closure();
     return $output;      return $output;
 }  }
   
 sub course_selection {  sub course_selection {
     my ($formname,$totcodes,$codetitles,$idlist,$idlist_titles,$crstype) = @_;      my ($formname,$totcodes,$codetitles,$idlist,$idlist_titles,$crstype,$standardnames) = @_;
     my $output = qq|      my $output = qq|
 <script type="text/javascript">  <script type="text/javascript">
 // <![CDATA[  // <![CDATA[
Line 1844  sub course_selection { Line 2058  sub course_selection {
         if ($numtitles > 0) {          if ($numtitles > 0) {
             $output .= '<input type="radio" name="coursepick" value="category" onclick="coursePick(this.form);alert('."'".&mt('Choose categories, from left to right')."'".')" />'.&mt('Pick courses by category:').' <br />';              $output .= '<input type="radio" name="coursepick" value="category" onclick="coursePick(this.form);alert('."'".&mt('Choose categories, from left to right')."'".')" />'.&mt('Pick courses by category:').' <br />';
             $output .= '<table><tr><td>'.$$codetitles[0].'<br />'."\n".              $output .= '<table><tr><td>'.$$codetitles[0].'<br />'."\n".
                '<select name="'.$$codetitles[0].                 '<select name="'.$standardnames->[0].
                '" onChange="setPick(this.form);courseSet('."'$$codetitles[0]'".')">'."\n".                 '" onChange="setPick(this.form);courseSet('."'$$codetitles[0]'".')">'."\n".
                ' <option value="-1" />Select'."\n";                 ' <option value="-1" />Select'."\n";
             my @items = ();              my @items = ();
Line 1874  sub course_selection { Line 2088  sub course_selection {
             $output .= '</select></td>';              $output .= '</select></td>';
             for (my $i=1; $i<$numtitles; $i++) {              for (my $i=1; $i<$numtitles; $i++) {
                 $output .= '<td>'.$$codetitles[$i].'<br />'."\n".                  $output .= '<td>'.$$codetitles[$i].'<br />'."\n".
                           '<select name="'.$$codetitles[$i].                            '<select name="'.$standardnames->[$i].
                           '" onChange="courseSet('."'$$codetitles[$i]'".')">'."\n".                            '" onChange="courseSet('."'$$codetitles[$i]'".')">'."\n".
                           '<option value="-1">&lt;-Pick '.$$codetitles[$i-1].'</option>'."\n".                            '<option value="-1">&lt;-Pick '.$$codetitles[$i-1].'</option>'."\n".
                           '</select>'."\n".                            '</select>'."\n".
Line 1966  sub course_custom_roles { Line 2180  sub course_custom_roles {
 }  }
   
   
   sub resource_info_box {
      my ($symb,$onlyfolderflag,$stuvcurrent,$stuvdisp)=@_;
      my $return='';
      if ($stuvcurrent ne '') {
          $return = '<div class="LC_left_float">';
      }
      if ($symb) {
          $return.=&Apache::loncommon::start_data_table();
          my ($map,$id,$resource)=&Apache::lonnet::decode_symb($symb);
          my $folder=&Apache::lonnet::gettitle($map);
          $return.=&Apache::loncommon::start_data_table_row().
                       '<th align="left">'.&mt('Folder:').'</th><td>'.$folder.'</td>'.
                       &Apache::loncommon::end_data_table_row();
          unless ($onlyfolderflag) {
             $return.=&Apache::loncommon::start_data_table_row().
                       '<th align="left">'.&mt('Resource:').'</th><td>'.&Apache::lonnet::gettitle($symb).'</td>'.
                       &Apache::loncommon::end_data_table_row();
          }
          if ($stuvcurrent ne '') {
              $return .= &Apache::loncommon::start_data_table_row().
                       '<th align="left">'.&mt("Student's current version:").'</th><td>'.$stuvcurrent.'</td>'.
                       &Apache::loncommon::end_data_table_row();
          }
          if ($stuvdisp ne '') {
              $return .= &Apache::loncommon::start_data_table_row().
                       '<th align="left">'.&mt("Student's version displayed:").'</th><td>'.$stuvdisp.'</td>'.
                       &Apache::loncommon::end_data_table_row();
          }
          $return.=&Apache::loncommon::end_data_table();
       } else {
          $return='<p><span class="LC_error">'.&mt('No context provided.').'</span></p>';
       }
       if ($stuvcurrent ne '') {
           $return .= '</div>';
       }
       return $return;
   }
   
 ##############################################  ##############################################
 ##############################################  ##############################################
   
Line 1977  sub course_custom_roles { Line 2229  sub course_custom_roles {
 # 1. number to display.  # 1. number to display.
 #    If input for number is empty only the title will be displayed.   #    If input for number is empty only the title will be displayed. 
 # 2. title text to display.  # 2. title text to display.
   # 3. optional id for the <div>
 # Outputs - a scalar containing html mark-up for the div.  # Outputs - a scalar containing html mark-up for the div.
   
 sub topic_bar {  sub topic_bar {
     my ($num,$title) = @_;      my ($num,$title,$id) = @_;
     my $number = '';      my $number = '';
     if ($num ne '') {      if ($num ne '') {
         $number = '<span>'.$num.'</span>';          $number = '<span>'.$num.'</span>';
     }      }
     return '<div class="LC_topic_bar">'.$number.$title.'</div>';      if ($id ne '') {
           $id = 'id="'.$id.'"';
       }
       return '<div class="LC_topic_bar" '.$id.'>'.$number.$title.'</div>';
 }  }
   
 ##############################################  ##############################################
Line 2022  sub echo_form_input { Line 2278  sub echo_form_input {
         if ($key =~ /^form\.(.+)$/) {          if ($key =~ /^form\.(.+)$/) {
             my $name = $1;              my $name = $1;
             my $match = 0;              my $match = 0;
             if ((!@{$excluded}) || (!grep/^$name$/,@{$excluded})) {              if (ref($excluded) eq 'ARRAY') {    
                 if (defined($regexps)) {                  next if (grep(/^\Q$name\E$/,@{$excluded}));
                     if (@{$regexps} > 0) {              }
                         foreach my $regexp (@{$regexps}) {              if (ref($regexps) eq 'ARRAY') {
                             if ($name =~ /\Q$regexp\E/) {                  if (@{$regexps} > 0) {
                                 $match = 1;                      foreach my $regexp (@{$regexps}) {
                                 last;                          if ($name =~ /$regexp/) {
                             }                              $match = 1;
                               last;
                         }                          }
                     }                      }
                 }                  }
                 if (!$match) {              }
                     if (ref($env{$key})) {              next if ($match);
                         foreach my $value (@{$env{$key}}) {              if (ref($env{$key}) eq 'ARRAY') {
                             $value = &HTML::Entities::encode($value,'<>&"');                  foreach my $value (@{$env{$key}}) {
                             $output .= '<input type="hidden" name="'.$name.                      $value = &HTML::Entities::encode($value,'<>&"');
                                              '" value="'.$value.'" />'."\n";                      $output .= '<input type="hidden" name="'.$name.
                         }                                 '" value="'.$value.'" />'."\n";
                     } else {  
                         my $value = &HTML::Entities::encode($env{$key},'<>&"');  
                         $output .= '<input type="hidden" name="'.$name.  
                                              '" value="'.$value.'" />'."\n";  
                     }  
                 }                  }
               } else {
                   my $value = &HTML::Entities::encode($env{$key},'<>&"');
                   $output .= '<input type="hidden" name="'.$name.
                              '" value="'.$value.'" />'."\n";
             }              }
         }          }
     }      }
Line 2204  sub set_form_elements { Line 2460  sub set_form_elements {
 ##############################################  ##############################################
 ##############################################  ##############################################
   
   sub file_submissionchk_js {
       my ($turninpaths,$multiples) = @_;
       my $overwritewarn = &mt('File(s) you uploaded for your submission will overwrite existing file(s) submitted for this item').'\\n'.
                         &mt('Continue submission and overwrite the file(s)?');
       my $delfilewarn = &mt('You have indicated you wish to remove some files previously included in your submission.').'\\n'.
                         &mt('Continue submission with these files removed?');
       my ($turninpathtext,$multtext,$arrayindexofjs);
       if (ref($turninpaths) eq 'HASH') {
           foreach my $key (sort(keys(%{$turninpaths}))) {
               $turninpathtext .= "    if (prefix == '$key') {\n".
                                  "        return '$turninpaths->{$key}';\n".
                                  "    }\n";
           }
       }
       $turninpathtext .= "    return '';\n";
       if (ref($multiples) eq 'HASH') {
           foreach my $key (sort(keys(%{$multiples}))) {
               $multtext .= "    if (prefix == '$key') {\n".
                            "        return '$multiples->{$key}';\n".
                            "    }\n";
           }
       }
       $multtext .= "    return '';\n";
   
       $arrayindexofjs = &Apache::loncommon::javascript_array_indexof();
       return <<"ENDSCRIPT";
   <script type="text/javascript">
   // <![CDATA[
   
   function file_submission_check(formname,path,multiresp) {
       var elemnum = formname.elements.length;
       if (elemnum == 0) {
           return true;
       }
       var alloverwrites = [];
       var alldelconfirm = [];
       var result = [];
       var submitter;
       var subprefix;
       var allsub = getIndexByName(formname,'all_submit');
       if (allsub == -1) {
           var idx = getIndexByName(formname,'submitted');
           if (idx != -1) {
               var subval = String(formname.elements[idx].value);
               submitter = subval.replace(/^part_/,'');
               result = overwritten_check(formname,path,multiresp,submitter);
               alloverwrites.push.apply(alloverwrites,result['overwrite']);
               alldelconfirm.push.apply(alldelconfirm,result['delete']);
           }
       } else {
           if (formname.elements[allsub].type == 'submit') {
               var partsub = /^\\d+\\.\\d+_submit_.+\$/;
               var allprefixes = [];
               var allparts = [];
               for (var i=0; i<formname.elements.length; i++) {
                   if (formname.elements[i].type == 'submit') {
                       var elemname = formname.elements[i].name;
                       var subname = String(elemname);
                       var savesub = String(elemname);
                       if (partsub.test(subname)) {
                           var prefix = subname.replace(/_submit_.+\$/,'');
                           if (allprefixes.indexOf(prefix) == -1) {
                               allprefixes.push(prefix);
                               allparts[prefix] = [];
                           }
                           var part = savesub.replace(/^\\d+\\.\\d+_submit_/,'');
                           allparts[prefix].push(part);
                       }
                   }
               }
               for (var k=0; k<allprefixes.length; k++) {
                   var idx = getIndexByName(formname,allprefixes[k]+'_submitted');
                   if (idx > -1) {
                       if (formname.elements[idx].value != 'yes') {
                           submitterval = formname.elements[idx].value;
                           submitter = submitterval.replace(/^part_/,'');
                           subprefix = allprefixes[k];
                           result = overwritten_check(formname,path,multiresp,submitter,subprefix);
                           alloverwrites.push.apply(alloverwrites,result['overwrite']);
                           alldelconfirm.push.apply(alldelconfirm,result['delete']);
                           break;
                       }
                   }
               }
               if (submitter == '' || submitter == undefined) {
                   for (var m=0; m<allprefixes.length; m++) {
                       for (var n=0; n<allparts[allprefixes[m]].length; n++) {
                           var result = overwritten_check(formname,path,multiresp,allparts[allprefixes[m]][n],allprefixes[m]);
                           alloverwrites.push.apply(alloverwrites,result['overwrite']);
                           alldelconfirm.push.apply(alldelconfirm,result['delete']);
                       }
                   }
               }
           }
       }
       if (alloverwrites.length > 0) {
           if (!confirm("$overwritewarn")) {
               for (var n=0; n<alloverwrites.length; n++) {
                   formname.elements[alloverwrites[n]].value = "";
               }
               return false;
           }
       }
       if (alldelconfirm.length > 0) {
           if (!confirm("$delfilewarn")) {
               for (var p=0; p<alldelconfirm.length; p++) {
                   formname.elements[alldelconfirm[p]].checked = false;
               }
               return false;
           }
       }
       return true;
   }
   
   function getIndexByName(formname,item) {
       for (var i=0;i<formname.elements.length;i++) {
           if (formname.elements[i].name == item) {
               return i;
           }
       }
       return -1;
   }
   
   function overwritten_check(formname,path,multiresp,part,prefix) {
       var result = [];
       result['overwrite'] = [];
       result['delete'] = [];
       var elemnum = formname.elements.length;
       if (elemnum == 0) {
           return result;
       }
       var uploadstr;
       var deletestr;
       if ((prefix != undefined) && (prefix != '')) {
           var prepend = prefix+'_';
           uploadstr = new RegExp("^"+prepend+"HWFILE"+part+".+\$");
           deletestr = new RegExp("^"+prepend+"HWFILE"+part+".+_\\\\d+_delete\$");
           multiresp = check_for_multiples(prepend);
           path = check_for_turninpath(prepend);
       } else {
           uploadstr = new RegExp("^HWFILE"+part+".+\$");
           deletestr = new RegExp("^HWFILE"+part+".+_\\\\d+_delete\$");
       }
       var alluploads = [];
       var allchecked = [];
       var allskipdel = [];
       var fnametrim = /[^\\/\\\\]+\$/;
       for (var i=0; i<formname.elements.length; i++) {
           var id = formname.elements[i].id;
           if (id != '') {
               if (uploadstr.test(id)) {
                   if (formname.elements[i].type == 'file') {
                       alluploads.push(id);
                   } else {
                       if (deletestr.test(id)) {
                           if (formname.elements[i].type == 'checkbox') {
                               if (formname.elements[i].checked) {
                                   allchecked.push(id);
                               }
                           }
                       }
                   }
               }
           }
       }
       for (var j=0; j<alluploads.length; j++) {
           var delstr = new RegExp("^"+alluploads[j]+"_\\\\d+_delete\$");
           var delboxes = [];
           for (var k=0; k<formname.elements.length; k++) {
               var id = formname.elements[k].id;
               if ((id != '') && (id != undefined)) {
                   if (delstr.test(id)) {
                       if (formname.elements[k].type == 'checkbox') {
                           delboxes.push(id);
                       }
                   }
               }
           }
           if (delboxes.length > 0) {
               if ((formname.elements[alluploads[j]].value != undefined) &&
                   (formname.elements[alluploads[j]].value != '')) {
                   var filepath = formname.elements[alluploads[j]].value;
                   var newfilename = fnametrim.exec(filepath);
                   if (newfilename != null) {
                       var filename = String(newfilename);
                       var nospaces = filename.replace(/\\s+/g,'_');
                       var nospecials = nospaces.replace(/[^\\/\\w\\.\\-]/g,'');
                       var cleanfilename = nospecials.replace(/\\.(\\d+\\.)/g,"_\$1");
                       if (cleanfilename != '') {
                           var fullpath = path+"/"+cleanfilename;
                           if (multiresp == 1) {
                               var partid = String(alluploads[i]);
                               var subdir = partid.replace(/^\\d*.?\\d*_?HWFILE/,'');
                               if (subdir != "" && subdir != undefined) {
                                   fullpath = path+"/"+subdir+"/"+cleanfilename;
                               }
                           }
                           for (var m=0; m<delboxes.length; m++) {
                               if (fullpath == formname.elements[delboxes[m]].value) {
                                   if (formname.elements[delboxes[m]].checked) {
                                       allskipdel.push(delboxes[m]);
                                   } else {
                                       result['overwrite'].push(alluploads[j]);
                                   }
                                   break;
                               }
                           }
                       }
                   }
               }
           }
       }
       if (allchecked.length > 0) {
           if (allskipdel.length > 0) {
               for (var n=0; n<allchecked.length; n++) {
                   if (allskipdel.indexOf(allchecked[n]) == -1) {
                       result['delete'].push(allchecked[n]);
                   }
               }
           } else {
               result['delete'].push.apply(result['delete'],allchecked);
           }
       }
       return result;
   }
   
   function check_for_multiples(prefix) {
   $multtext
   }
   
   function check_for_turninpath(prefix) {
   $turninpathtext
   }
   
   // ]]>
   </script>
   
   $arrayindexofjs
   
   ENDSCRIPT
   }
   
   ##############################################
   ##############################################
   
   sub resize_scrollbox_js {
       my ($context,$tabidstr) = @_;
       my (%names,$paddingwfrac,$offsetwfrac,$offsetv,$minw,$minv);
       if ($context eq 'docs') {
           %names = (
                      boxw   => 'contenteditor',
                      item   => 'contentlist',
                      header => 'uploadfileresult',
                      scroll => 'contentscroll',
                      boxh   => 'contenteditor',
                    );
           $paddingwfrac = 0.09; 
           $offsetwfrac = 0.015;
           $offsetv = 20;
           $minw = 250;
           $minv = 200;
       } elsif ($context eq 'params') {
           %names = (
                      boxw   => 'parameditor',
                      item   => 'mapmenuinner',
                      header => 'parmstep1',
                      scroll => 'mapmenuscroll',
                      boxh   => 'parmlevel',
                    );
           $paddingwfrac = 0.2;
           $offsetwfrac = 0.015;
           $offsetv = 80;
           $minw = 100;
           $minv = 100; 
       }
       my $viewport_js = &Apache::loncommon::viewport_geometry_js();
       my $output = '
   
   window.onresize=callResize;
   
   ';
       if ($context eq 'docs') {
           $output .= '
   var activeTab;
   ';
       }
       $output .=  <<"FIRST";
   
   $viewport_js
   
   function resize_scrollbox(scrollboxname,chkw,chkh) {
       var scrollboxid = 'div_'+scrollboxname;
       var scrolltableid = 'table_'+scrollboxname;
       var scrollbox;
       var scrolltable;
   
       if (document.getElementById("$names{'boxw'}") == null) {
           return;
       }
   
       if (document.getElementById(scrollboxid) == null) {
           return;
       } else {
           scrollbox = document.getElementById(scrollboxid);
       }
   
   
       if (document.getElementById(scrolltableid) == null) {
           return;
       } else {
           scrolltable = document.getElementById(scrolltableid);
       }
   
       init_geometry();
       var vph = Geometry.getViewportHeight();
       var vpw = Geometry.getViewportWidth();
   
   FIRST
       if ($context eq 'docs') {
           $output .= "
       var alltabs = ['$tabidstr'];
   ";
       } elsif ($context eq 'params') {
           $output .= "
       if (document.getElementById('$names{'boxh'}') == null) {
           return;
       }
   ";
       }
       $output .= <<"SECOND";
       var listwchange;
       if (chkw == 1) {
           var boxw = document.getElementById("$names{'boxw'}").offsetWidth;
           var itemw;
           var itemid = document.getElementById("$names{'item'}");
           if (itemid != null) {
               itemw = itemid.offsetWidth;
           }
           var itemwstart = itemw;
   
           var scrollboxw = scrollbox.offsetWidth;
           var scrollboxscrollw = scrollbox.scrollWidth;
   
           var offsetw = parseInt(vpw * $offsetwfrac);
           var paddingw = parseInt(vpw * $paddingwfrac);
   
           var minscrollboxw = $minw;
           var maxcolw = 0;
   SECOND
       if ($context eq 'docs') {
           $output .= <<"DOCSONE";
           var actabw = 0;
           for (var i=0; i<alltabs.length; i++) {
               if (activeTab == alltabs[i]) {
                   actabw = document.getElementById(alltabs[i]).offsetWidth;
                   if (actabw > maxcolw) {
                       maxcolw = actabw;
                   }
               } else {
                   if (document.getElementById(alltabs[i]) != null) {
                       var thistab = document.getElementById(alltabs[i]);
                       thistab.style.visibility = 'hidden';
                       thistab.style.display = 'block';
                       var tabw = document.getElementById(alltabs[i]).offsetWidth;
                       thistab.style.display = 'none';
                       thistab.style.visibility = '';
                       if (tabw > maxcolw) {
                           maxcolw = tabw;
                       }
                   }
               }
           }
   DOCSONE
       } elsif ($context eq 'params') {
           $output .= <<"PARAMSONE";
           var parmlevelrows = new Array();
           var mapmenucells = new Array();
           parmlevelrows = document.getElementById("$names{'boxh'}").rows;
           var numrows = parmlevelrows.length;
           if (numrows > 1) {
               mapmenucells = parmlevelrows[2].getElementsByTagName('td');
           }
           maxcolw = mapmenucells[0].offsetWidth;
   PARAMSONE
       }
       $output .= <<"THIRD";
           if (maxcolw > 0) {
               var newscrollboxw;
               if (maxcolw+paddingw+scrollboxscrollw<boxw) {
                   newscrollboxw = boxw-paddingw-maxcolw;
                   if (newscrollboxw < minscrollboxw) {
                       newscrollboxw = minscrollboxw;
                   }
                   scrollbox.style.width = newscrollboxw+"px";
                   if (newscrollboxw != scrollboxw) {
                       var newitemw = newscrollboxw-offsetw;
                       itemid.style.width = newitemw+"px";
                   }
               } else {
                   newscrollboxw = boxw-paddingw-maxcolw;
                   if (newscrollboxw < minscrollboxw) {
                       newscrollboxw = minscrollboxw;
                   }
                   scrollbox.style.width = newscrollboxw+"px";
                   if (newscrollboxw != scrollboxw) {
                       var newitemw = newscrollboxw-offsetw;
                       itemid.style.width = newitemw+"px";
                   }
               }
   
               if (newscrollboxw != scrollboxw) {
                   var newscrolltablew = newscrollboxw+offsetw;
                   scrolltable.style.width = newscrolltablew+"px";
               }
           }
   
           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;
           var secondaryheight = document.getElementById('LC_secondary_menu').offsetHeight;
           var crumbsheight = document.getElementById('LC_breadcrumbs').offsetHeight;
           var dccidheight = 0;
           if (document.getElementById('dccid') != null) {
               dccidheight = document.getElementById('dccid').offsetHeight;
           }
           var headerheight = 0;
           if (document.getElementById("$names{'header'}") != null) {
               headerheight = document.getElementById("$names{'header'}").offsetHeight;
           }
           var tabbedheight = document.getElementById("tabbededitor").offsetHeight;
           var boxheight = document.getElementById("$names{'boxh'}").offsetHeight;
           var freevspace = vph-(primaryheight+secondaryheight+crumbsheight+dccidheight+headerheight+tabbedheight+boxheight);
   
           var scrollboxheight = scrollbox.offsetHeight;
           var scrollboxscrollheight = scrollbox.scrollHeight;
   
           var minvscrollbox = $minv;
           var offsetv = $offsetv;
           var newscrollboxheight;
           if (freevspace < 0) {
               newscrollboxheight = scrollboxheight+freevspace-offsetv;
               if (newscrollboxheight < minvscrollbox) {
                   newscrollboxheight = minvscrollbox;
               }
               scrollbox.style.height = newscrollboxheight + "px";
           } else {
               if (scrollboxscrollheight > scrollboxheight) {
                   if (freevspace > offsetv) {
                       newscrollboxheight = scrollboxheight+freevspace-offsetv;
                       if (newscrollboxheight < minvscrollbox) {
                           newscrollboxheight = minvscrollbox;
                       }
                       scrollbox.style.height = newscrollboxheight+"px";
                   }
               }
           }
           scrollboxheight = scrollbox.offsetHeight;
           var itemh = document.getElementById("$names{'item'}").offsetHeight;
   
           if (scrollboxscrollheight <= scrollboxheight) {
               if ((itemh+offsetv)<scrollboxheight) {
                   newscrollheight = itemh+offsetv;
                   scrollbox.style.height = newscrollheight+"px";
               }
           }
       }
       return;
   }
   
   function callResize() {
       var timer;
       clearTimeout(timer);
       timer=setTimeout('resize_scrollbox("$names{'scroll'}","1","1")',500);
   }
   
   FOURTH
       return $output;
   }
   
   
   ##############################################
   ##############################################
   
 # javascript_valid_email  # javascript_valid_email
 #  #
 # Generates javascript to validate an e-mail address.  # Generates javascript to validate an e-mail address.
Line 2319  sub scripttag { Line 3084  sub scripttag {
     return htmltag('script', $content, {type => 'text/javascript'});      return htmltag('script', $content, {type => 'text/javascript'});
 };  };
   
   =pod
   
 =item list_from_array( \@array, { listattr =>{}, itemattr =>{} } )  =item &list_from_array( \@array, { listattr =>{}, itemattr =>{} } )
   
 Constructs a XHTML list from \@array.  Constructs a XHTML list from \@array.
   
 input:  input: 
   
 =over  =over
   
 =item \@array  =item \@array 
   
 A reference to the array containing text that will be wrapped in <li></li> tags.  A reference to the array containing text that will be wrapped in <li></li> tags.
   
 =item { listattr => {}, itemattr =>{} }  =item { listattr => {}, itemattr =>{} } 
   
 Attributes for <ul> and <li> passed in as hash references.  Attributes for <ul> and <li> passed in as hash references. 
 See htmltag() for more details.  See htmltag() for more details.
   
 =back  =back
    
   returns: XHTML list as String. 
   
 returns: XHTML list as String.  =cut   
   
 =cut  
   
 # \@items, {listattr => { class => 'abc', id => 'xyx' }, itemattr => {class => 'abc', id => 'xyx'}}  # \@items, {listattr => { class => 'abc', id => 'xyx' }, itemattr => {class => 'abc', id => 'xyx'}}
 sub list_from_array {  sub list_from_array {
     my ($items, $args) = @_;      my ($items, $args) = @_;
       return unless (ref($items) eq 'ARRAY');
     return unless scalar @$items;      return unless scalar @$items;
     my ($ul, $li) = inittags( qw(ul li) );      my ($ul, $li) = inittags( qw(ul li) );
     my $listitems = join '', map { $li->($_, $args->{itemattr}) } @$items;      my $listitems = join '', map { $li->($_, $args->{itemattr}) } @$items;
Line 2410  sub generate_menu { Line 3177  sub generate_menu {
                                 $$link{alttext} : $$link{linktext})                                  $$link{alttext} : $$link{linktext})
                             }), {                              }), {
                             href  => $$link{url},                              href  => $$link{url},
                             title => mt($$link{linktitle})                              title => mt($$link{linktitle}),
                               class => 'LC_menubuttons_link'
                             }).                              }).
                         $a->(mt($$link{linktext}), {                          $a->(mt($$link{linktext}), {
                             href  => $$link{url},                              href  => $$link{url},
Line 2444  sub generate_menu { Line 3212  sub generate_menu {
   
 =pod  =pod
   
 =item &start_funclist  =item &start_funclist()
   
 Start list of available functions  Start list of available functions
   
Line 2484  sub start_funclist { Line 3252  sub start_funclist {
   
 =pod  =pod
   
 =item &add_item_funclist  =item &add_item_funclist()
   
 Adds an item to the list of available functions  Adds an item to the list of available functions
   
Line 2510  sub add_item_funclist { Line 3278  sub add_item_funclist {
   
 =pod  =pod
   
 =item &end_funclist  =item &end_funclist()
   
 End list of available functions  End list of available functions
   
Line 2531  sub end_funclist { Line 3299  sub end_funclist {
   
 =pod  =pod
   
 =item funclist_from_array( \@array, {legend => 'text for legend'} )  =item &funclist_from_array( \@array, {legend => 'text for legend'} )
   
 Constructs a XHTML list from \@array with the first item being visually  Constructs a XHTML list from \@array with the first item being visually
 highlighted and set to the value of legend or 'Functions' if legend is  highlighted and set to the value of legend or 'Functions' if legend is
 empty.  empty. 
   
 =over  =over
   
Line 2549  A string that's used as visually highlig Line 3317  A string that's used as visually highlig
 it's value evaluates to false.  it's value evaluates to false.
   
 =back  =back
    
 returns: XHTML list as string.  returns: XHTML list as string. 
   
 =back  =back
   
 =cut  =cut  
   
 sub funclist_from_array {  sub funclist_from_array {
     my ($items, $args) = @_;      my ($items, $args) = @_;
       return unless(ref($items) eq 'ARRAY');
     $args->{legend} ||= mt('Functions');      $args->{legend} ||= mt('Functions');
     return list_from_array( [$args->{legend}, @$items],      return list_from_array( [$args->{legend}, @$items], 
                { listattr => {class => 'LC_funclist'} });                 { listattr => {class => 'LC_funclist'} });
 }  }   
   
 1;  1;
   

Removed from v.1.253.2.7  
changed lines
  Added in v.1.321


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>