Annotation of loncom/interface/lonhtmlcommon.pm, revision 1.182.2.2

1.2       www         1: # The LearningOnline Network with CAPA
                      2: # a pile of common html routines
                      3: #
1.182.2.2! raeburn     4: # $Id: lonhtmlcommon.pm,v 1.182.2.1 2009/01/12 01:53:38 raeburn Exp $
1.2       www         5: #
                      6: # Copyright Michigan State University Board of Trustees
                      7: #
                      8: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
                      9: #
                     10: # LON-CAPA is free software; you can redistribute it and/or modify
                     11: # it under the terms of the GNU General Public License as published by
                     12: # the Free Software Foundation; either version 2 of the License, or
                     13: # (at your option) any later version.
                     14: #
                     15: # LON-CAPA is distributed in the hope that it will be useful,
                     16: # but WITHOUT ANY WARRANTY; without even the implied warranty of
                     17: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     18: # GNU General Public License for more details.
                     19: #
                     20: # You should have received a copy of the GNU General Public License
                     21: # along with LON-CAPA; if not, write to the Free Software
                     22: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
                     23: #
                     24: # /home/httpd/html/adm/gpl.txt
                     25: #
                     26: # http://www.lon-capa.org/
                     27: #
1.10      matthew    28: ######################################################################
                     29: ######################################################################
                     30: 
                     31: =pod
                     32: 
                     33: =head1 NAME
                     34: 
                     35: Apache::lonhtmlcommon - routines to do common html things
                     36: 
                     37: =head1 SYNOPSIS
                     38: 
                     39: Referenced by other mod_perl Apache modules.
                     40: 
                     41: =head1 INTRODUCTION
                     42: 
                     43: lonhtmlcommon is a collection of subroutines used to present information
                     44: in a consistent html format, or provide other functionality related to
                     45: html.
                     46: 
                     47: =head2 General Subroutines
                     48: 
                     49: =over 4
                     50: 
                     51: =cut 
                     52: 
                     53: ######################################################################
                     54: ######################################################################
1.2       www        55: 
1.1       stredwic   56: package Apache::lonhtmlcommon;
                     57: 
1.104     albertel   58: use strict;
1.10      matthew    59: use Time::Local;
1.47      sakharuk   60: use Time::HiRes;
1.30      www        61: use Apache::lonlocal;
1.104     albertel   62: use Apache::lonnet;
1.130     www        63: use LONCAPA;
1.1       stredwic   64: 
1.176     foxr       65: 
                     66: ##############################################
                     67: ##############################################
                     68: 
                     69: =pod
                     70: 
1.177     raeburn    71: =item dragmath_button
1.176     foxr       72: 
1.177     raeburn    73: Creates a button that launches a dragmath popup-window, in which an 
                     74: expression can be edited and pasted as LaTeX into a specified textarea. 
                     75: 
                     76:   textarea - Name of the textarea to edit.
                     77:   helpicon - If true, show a help icon to the right of the button.
1.176     foxr       78: 
                     79: =cut
                     80: 
1.177     raeburn    81: sub dragmath_button {
                     82:     my ($textarea,$helpicon) = @_;
                     83:     my $help_text; 
                     84:     if ($helpicon) {
                     85:         $help_text = &Apache::loncommon::help_open_topic('Authoring_Math_Editor');
                     86:     }
1.178     bisitz     87:     my $buttontext=&mt('Edit Math');
1.177     raeburn    88:     return <<ENDDRAGMATH;
1.178     bisitz     89:                 <input type="button" value="$buttontext", onclick="javascript:mathedit('$textarea',document)" />$help_text
1.177     raeburn    90: ENDDRAGMATH
                     91: }
                     92: 
1.176     foxr       93: ##############################################
                     94: 
1.177     raeburn    95: =pod
                     96: 
                     97: =item dragmath_js
                     98: 
                     99: Javascript used to open pop-up window containing dragmath applet which 
                    100: can be used to paste LaTeX into a textarea.
                    101:  
                    102: =cut
1.176     foxr      103: 
1.177     raeburn   104: sub dragmath_js {
1.182     foxr      105:     my ($popup) = @_;
1.177     raeburn   106:     return <<ENDDRAGMATHJS;
                    107:                 <script type="text/javascript">
1.176     foxr      108:                   function mathedit(textarea, doc) {
                    109:                      targetEntry = textarea;
1.177     raeburn   110:                      targetDoc   = doc;
1.182     foxr      111:                      newwin  = window.open("/adm/dragmath/applet/$popup.html","","width=565,height=500,resizable");
1.176     foxr      112:                   }
                    113:                 </script>
1.177     raeburn   114: 
                    115: ENDDRAGMATHJS
1.176     foxr      116: }
                    117: 
1.182     foxr      118: 
1.40      www       119: ##############################################
                    120: ##############################################
                    121: 
                    122: =pod
                    123: 
                    124: =item authorbombs
                    125: 
                    126: =cut
                    127: 
                    128: ##############################################
                    129: ##############################################
                    130: 
                    131: sub authorbombs {
                    132:     my $url=shift;
                    133:     $url=&Apache::lonnet::declutter($url);
1.155     albertel  134:     my ($udom,$uname)=($url=~m{^($LONCAPA::domain_re)/($LONCAPA::username_re)/});
1.40      www       135:     my %bombs=&Apache::lonmsg::all_url_author_res_msg($uname,$udom);
                    136:     foreach (keys %bombs) {
                    137: 	if ($_=~/^$udom\/$uname\//) {
                    138: 	    return '<a href="/adm/bombs/'.$url.
1.103     albertel  139: 		'"><img src="'.&Apache::loncommon::lonhttpdurl('/adm/lonMisc/bomb.gif').'" border="0" /></a>'.
1.40      www       140: 		&Apache::loncommon::help_open_topic('About_Bombs');
                    141: 	}
                    142:     }
                    143:     return '';
                    144: }
1.26      matthew   145: 
                    146: ##############################################
                    147: ##############################################
                    148: 
1.41      www       149: sub recent_filename {
                    150:     my $area=shift;
1.130     www       151:     return 'nohist_recent_'.&escape($area);
1.41      www       152: }
                    153: 
                    154: sub store_recent {
1.136     albertel  155:     my ($area,$name,$value,$freeze)=@_;
1.41      www       156:     my $file=&recent_filename($area);
                    157:     my %recent=&Apache::lonnet::dump($file);
1.111     www       158:     if (scalar(keys(%recent))>20) {
1.41      www       159: # remove oldest value
1.136     albertel  160: 	my $oldest=time();
1.41      www       161: 	my $delkey='';
1.136     albertel  162: 	foreach my $item (keys(%recent)) {
                    163: 	    my $thistime=(split(/\&/,$recent{$item}))[0];
                    164: 	    if (($thistime ne "always_include") && ($thistime<$oldest)) {
1.41      www       165: 		$oldest=$thistime;
1.136     albertel  166: 		$delkey=$item;
1.41      www       167: 	    }
                    168: 	}
                    169: 	&Apache::lonnet::del($file,[$delkey]);
                    170:     }
                    171: # store new value
1.136     albertel  172:     my $timestamp;
                    173:     if ($freeze) {
                    174:         $timestamp = "always_include";
                    175:     } else {
                    176:         $timestamp = time();
                    177:     }   
1.41      www       178:     &Apache::lonnet::put($file,{ $name => 
1.136     albertel  179: 				 $timestamp.'&'.&escape($value) });
1.41      www       180: }
                    181: 
1.89      banghart  182: sub remove_recent {
                    183:     my ($area,$names)=@_;
                    184:     my $file=&recent_filename($area);
                    185:     return &Apache::lonnet::del($file,$names);
                    186: }
                    187: 
1.41      www       188: sub select_recent {
                    189:     my ($area,$fieldname,$event)=@_;
                    190:     my %recent=&Apache::lonnet::dump(&recent_filename($area));
                    191:     my $return="\n<select name='$fieldname'".
1.96      albertel  192: 	($event?" onchange='$event'":'').
1.41      www       193: 	">\n<option value=''>--- ".&mt('Recent')." ---</option>";
1.136     albertel  194:     foreach my $value (sort(keys(%recent))) {
                    195: 	unless ($value =~/^error\:/) {
                    196: 	    my $escaped = &Apache::loncommon::escape_url($value);
1.160     albertel  197: 	    &Apache::loncommon::inhibit_menu_check(\$escaped);
1.94      foxr      198: 	    $return.="\n<option value='$escaped'>".
1.136     albertel  199: 		&unescape((split(/\&/,$recent{$value}))[1]).
1.41      www       200: 		'</option>';
                    201: 	}
                    202:     }
                    203:     $return.="\n</select>\n";
                    204:     return $return;
                    205: }
                    206: 
1.97      albertel  207: sub get_recent {
                    208:     my ($area, $n) = @_;
                    209:     my %recent=&Apache::lonnet::dump(&recent_filename($area));
                    210: 
                    211: # Create hash with key as time and recent as value
1.136     albertel  212: # Begin filling return_hash with any 'always_include' option
1.97      albertel  213:     my %time_hash = ();
1.136     albertel  214:     my %return_hash = ();
                    215:     foreach my $item (keys %recent) {
                    216:         my ($thistime,$thisvalue)=(split(/\&/,$recent{$item}));
                    217:         if ($thistime eq 'always_include') {
                    218:             $return_hash{$item} = &unescape($thisvalue);
                    219:             $n--;
                    220:         } else {
                    221:             $time_hash{$thistime} = $item;
1.133     albertel  222:         }
1.97      albertel  223:     }
                    224: 
                    225: # Sort by decreasing time and return key value pairs
                    226:     my $idx = 1;
1.136     albertel  227:     foreach my $item (reverse(sort(keys(%time_hash)))) {
                    228:        $return_hash{$time_hash{$item}} =
                    229:                   &unescape((split(/\&/,$recent{$time_hash{$item}}))[1]);
1.97      albertel  230:        if ($n && ($idx++ >= $n)) {last;}
                    231:     }
                    232: 
                    233:     return %return_hash;
                    234: }
                    235: 
1.136     albertel  236: sub get_recent_frozen {
                    237:     my ($area) = @_;
                    238:     my %recent=&Apache::lonnet::dump(&recent_filename($area));
                    239: 
                    240: # Create hash with all 'frozen' items
                    241:     my %return_hash = ();
                    242:     foreach my $item (keys(%recent)) {
                    243:         my ($thistime,$thisvalue)=(split(/\&/,$recent{$item}));
                    244:         if ($thistime eq 'always_include') {
                    245:             $return_hash{$item} = &unescape($thisvalue);
                    246:         }
                    247:     }
                    248:     return %return_hash;
                    249: }
                    250: 
1.97      albertel  251: 
1.41      www       252: 
1.26      matthew   253: =pod
                    254: 
                    255: =item textbox
                    256: 
                    257: =cut
                    258: 
                    259: ##############################################
                    260: ##############################################
                    261: sub textbox {
                    262:     my ($name,$value,$size,$special) = @_;
                    263:     $size = 40 if (! defined($size));
1.128     albertel  264:     $value = &HTML::Entities::encode($value,'<>&"');
1.26      matthew   265:     my $Str = '<input type="text" name="'.$name.'" size="'.$size.'" '.
                    266:         'value="'.$value.'" '.$special.' />';
                    267:     return $Str;
                    268: }
                    269: 
                    270: ##############################################
                    271: ##############################################
                    272: 
                    273: =pod
                    274: 
                    275: =item checkbox
                    276: 
                    277: =cut
                    278: 
                    279: ##############################################
                    280: ##############################################
                    281: sub checkbox {
1.68      matthew   282:     my ($name,$checked,$value) = @_;
                    283:     my $Str = '<input type="checkbox" name="'.$name.'" ';
                    284:     if (defined($value)) {
                    285:         $Str .= 'value="'.$value.'"';
                    286:     } 
                    287:     if ($checked) {
                    288:         $Str .= ' checked="1"';
                    289:     }
                    290:     $Str .= ' />';
1.26      matthew   291:     return $Str;
                    292: }
                    293: 
1.120     albertel  294: 
                    295: =pod
                    296: 
                    297: =item radiobutton
                    298: 
                    299: =cut
                    300: 
                    301: ##############################################
                    302: ##############################################
                    303: sub radio {
                    304:     my ($name,$checked,$value) = @_;
                    305:     my $Str = '<input type="radio" name="'.$name.'" ';
                    306:     if (defined($value)) {
                    307:         $Str .= 'value="'.$value.'"';
                    308:     } 
                    309:     if ($checked eq $value) {
                    310:         $Str .= ' checked="1"';
                    311:     }
                    312:     $Str .= ' />';
                    313:     return $Str;
                    314: }
                    315: 
1.10      matthew   316: ##############################################
                    317: ##############################################
                    318: 
                    319: =pod
                    320: 
                    321: =item &date_setter
                    322: 
1.22      matthew   323: &date_setter returns html and javascript for a compact date-setting form.
                    324: To retrieve values from it, use &get_date_from_form().
                    325: 
1.10      matthew   326: Inputs
                    327: 
                    328: =over 4
                    329: 
                    330: =item $dname 
                    331: 
                    332: The name to prepend to the form elements.  
                    333: The form elements defined will be dname_year, dname_month, dname_day,
                    334: dname_hour, dname_min, and dname_sec.
                    335: 
                    336: =item $currentvalue
                    337: 
                    338: The current setting for this time parameter.  A unix format time
                    339: (time in seconds since the beginning of Jan 1st, 1970, GMT.  
                    340: An undefined value is taken to indicate the value is the current time.
                    341: Also, to be explicit, a value of 'now' also indicates the current time.
                    342: 
1.26      matthew   343: =item $special
                    344: 
                    345: Additional html/javascript to be associated with each element in
                    346: the date_setter.  See lonparmset for example usage.
                    347: 
1.59      matthew   348: =item $includeempty 
                    349: 
                    350: =item $state
                    351: 
                    352: Specifies the initial state of the form elements.  Either 'disabled' or empty.
                    353: Defaults to empty, which indiciates the form elements are not disabled. 
                    354: 
1.22      matthew   355: =back
                    356: 
                    357: Bugs
                    358: 
                    359: The method used to restrict user input will fail in the year 2400.
                    360: 
1.10      matthew   361: =cut
                    362: 
                    363: ##############################################
                    364: ##############################################
                    365: sub date_setter {
1.67      matthew   366:     my ($formname,$dname,$currentvalue,$special,$includeempty,$state,
1.134     raeburn   367:         $no_hh_mm_ss,$defhour,$defmin,$defsec,$nolink) = @_;
1.175     raeburn   368:     my $now = time;
1.107     www       369:     my $wasdefined=1;
1.59      matthew   370:     if (! defined($state) || $state ne 'disabled') {
                    371:         $state = '';
                    372:     }
1.67      matthew   373:     if (! defined($no_hh_mm_ss)) {
                    374:         $no_hh_mm_ss = 0;
                    375:     }
1.110     www       376:     if ($currentvalue eq 'now') {
1.175     raeburn   377: 	$currentvalue = $now;
1.110     www       378:     }
                    379:     if ((!defined($currentvalue)) || ($currentvalue eq '')) {
                    380: 	$wasdefined=0;
                    381: 	if ($includeempty) {
                    382: 	    $currentvalue = 0;
                    383: 	} else {
1.175     raeburn   384: 	    $currentvalue = $now;
1.39      www       385: 	}
1.10      matthew   386:     }
                    387:     # other potentially useful values:     wkday,yrday,is_daylight_savings
1.175     raeburn   388:     my $tzname;
1.65      albertel  389:     my ($sec,$min,$hour,$mday,$month,$year)=('','',undef,'','','');
1.39      www       390:     if ($currentvalue) {
1.175     raeburn   391:         ($tzname,$sec,$min,$hour,$mday,$month,$year) = &get_timedates($currentvalue); 
1.39      www       392:     }
1.107     www       393:     unless ($wasdefined) {
1.175     raeburn   394:         ($tzname,$sec,$min,$hour,$mday,$month,$year) = &get_timedates($now);
1.110     www       395: 	if (($defhour) || ($defmin) || ($defsec)) {
                    396: 	    $sec=($defsec?$defsec:0);
                    397: 	    $min=($defmin?$defmin:0);
                    398: 	    $hour=($defhour?$defhour:0);
                    399: 	} elsif (!$includeempty) {
                    400: 	    $sec=0;
                    401: 	    $min=0;
                    402: 	    $hour=0;
                    403: 	}
1.107     www       404:     }
1.10      matthew   405:     my $result = "\n<!-- $dname date setting form -->\n";
                    406:     $result .= <<ENDJS;
1.135     albertel  407: <script type="text/javascript">
1.10      matthew   408:     function $dname\_checkday() {
                    409:         var day   = document.$formname.$dname\_day.value;
                    410:         var month = document.$formname.$dname\_month.value;
                    411:         var year  = document.$formname.$dname\_year.value;
                    412:         var valid = true;
                    413:         if (day < 1) {
                    414:             document.$formname.$dname\_day.value = 1;
                    415:         } 
                    416:         if (day > 31) {
                    417:             document.$formname.$dname\_day.value = 31;
                    418:         }
                    419:         if ((month == 1)  || (month == 3)  || (month == 5)  ||
                    420:             (month == 7)  || (month == 8)  || (month == 10) ||
                    421:             (month == 12)) {
                    422:             if (day > 31) {
                    423:                 document.$formname.$dname\_day.value = 31;
                    424:                 day = 31;
                    425:             }
                    426:         } else if (month == 2 ) {
                    427:             if ((year % 4 == 0) && (year % 100 != 0)) {
                    428:                 if (day > 29) {
                    429:                     document.$formname.$dname\_day.value = 29;
                    430:                 }
                    431:             } else if (day > 29) {
                    432:                 document.$formname.$dname\_day.value = 28;
                    433:             }
                    434:         } else if (day > 30) {
                    435:             document.$formname.$dname\_day.value = 30;
                    436:         }
                    437:     }
1.95      matthew   438:     
1.59      matthew   439:     function $dname\_disable() {
                    440:         document.$formname.$dname\_month.disabled=true;
                    441:         document.$formname.$dname\_day.disabled=true;
                    442:         document.$formname.$dname\_year.disabled=true;
                    443:         document.$formname.$dname\_hour.disabled=true;
                    444:         document.$formname.$dname\_minute.disabled=true;
                    445:         document.$formname.$dname\_second.disabled=true;
                    446:     }
                    447: 
                    448:     function $dname\_enable() {
                    449:         document.$formname.$dname\_month.disabled=false;
                    450:         document.$formname.$dname\_day.disabled=false;
                    451:         document.$formname.$dname\_year.disabled=false;
                    452:         document.$formname.$dname\_hour.disabled=false;
                    453:         document.$formname.$dname\_minute.disabled=false;
                    454:         document.$formname.$dname\_second.disabled=false;        
                    455:     }
                    456: 
1.29      www       457:     function $dname\_opencalendar() {
1.59      matthew   458:         if (! document.$formname.$dname\_month.disabled) {
                    459:             var calwin=window.open(
1.29      www       460: "/adm/announcements?pickdate=yes&formname=$formname&element=$dname&month="+
                    461: document.$formname.$dname\_month.value+"&year="+
                    462: document.$formname.$dname\_year.value,
                    463:              "LONCAPAcal",
                    464:               "height=350,width=350,scrollbars=yes,resizable=yes,menubar=no");
1.59      matthew   465:         }
1.29      www       466: 
                    467:     }
1.10      matthew   468: </script>
                    469: ENDJS
1.135     albertel  470:     $result .= '  <span style="white-space: nowrap;">';
1.96      albertel  471:     my $monthselector = qq{<select name="$dname\_month" $special $state onchange="javascript:$dname\_checkday()" >};
1.67      matthew   472:     # Month
1.10      matthew   473:     my @Months = qw/January February  March     April   May      June 
                    474:                     July    August    September October November December/;
                    475:     # Pad @Months with a bogus value to make indexing easier
                    476:     unshift(@Months,'If you can read this an error occurred');
1.95      matthew   477:     if ($includeempty) { $monthselector.="<option value=''></option>"; }
1.10      matthew   478:     for(my $m = 1;$m <=$#Months;$m++) {
1.95      matthew   479:         $monthselector .= qq{      <option value="$m" };
                    480:         $monthselector .= "selected " if ($m-1 eq $month);
                    481:         $monthselector .= '> '.&mt($Months[$m]).' </option>';
1.10      matthew   482:     }
1.95      matthew   483:     $monthselector.= '  </select>';
1.67      matthew   484:     # Day
1.96      albertel  485:     my $dayselector = qq{<input type="text" name="$dname\_day" $state value="$mday" size="3" $special onchange="javascript:$dname\_checkday()" />};
1.67      matthew   486:     # Year
1.96      albertel  487:     my $yearselector = qq{<input type="year" name="$dname\_year" $state value="$year" size="5" $special onchange="javascript:$dname\_checkday()" />};
1.95      matthew   488:     #
                    489:     my $hourselector = qq{<select name="$dname\_hour" $special $state >};
                    490:     if ($includeempty) { 
                    491:         $hourselector.=qq{<option value=''></option>};
                    492:     }
                    493:     for (my $h = 0;$h<24;$h++) {
                    494:         $hourselector .= qq{<option value="$h" };
                    495:         $hourselector .= "selected " if (defined($hour) && $hour == $h);
                    496:         $hourselector .= ">";
                    497:         my $timest='';
                    498:         if ($h == 0) {
                    499:             $timest .= "12 am";
                    500:         } elsif($h == 12) {
                    501:             $timest .= "12 noon";
                    502:         } elsif($h < 12) {
                    503:             $timest .= "$h am";
                    504:         } else {
                    505:             $timest .= $h-12 ." pm";
                    506:         }
                    507:         $timest=&mt($timest);
                    508:         $hourselector .= $timest." </option>\n";
                    509:     }
                    510:     $hourselector .= "  </select>\n";
                    511:     my $minuteselector = qq{<input type="text" name="$dname\_minute" $special $state value="$min" size="3" />};
                    512:     my $secondselector= qq{<input type="text" name="$dname\_second" $special $state value="$sec" size="3" />};
1.134     raeburn   513:     my $cal_link;
                    514:     if (!$nolink) {
                    515:         $cal_link = qq{<a href="javascript:$dname\_opencalendar()">};
                    516:     }
1.95      matthew   517:     #
1.175     raeburn   518:     my $tzone = ' '.$tzname.' ';
1.95      matthew   519:     if ($no_hh_mm_ss) {
1.134     raeburn   520:         $result .= &mt('[_1] [_2] [_3] ',
1.174     raeburn   521:                        $monthselector,$dayselector,$yearselector).
                    522:                    $tzone;
1.134     raeburn   523:         if (!$nolink) {
1.141     albertel  524:             $result .= &mt('[_1]Select Date[_2]',$cal_link,'</a>');
1.134     raeburn   525:         }
1.95      matthew   526:     } else {
1.134     raeburn   527:         $result .= &mt('[_1] [_2] [_3] [_4] [_5]m [_6]s ',
                    528:                       $monthselector,$dayselector,$yearselector,
1.174     raeburn   529:                       $hourselector,$minuteselector,$secondselector).
                    530:                    $tzone;
1.134     raeburn   531:         if (!$nolink) {
1.141     albertel  532:             $result .= &mt('[_1]Select Date[_2]',$cal_link,'</a>');
1.134     raeburn   533:         }
1.67      matthew   534:     }
1.135     albertel  535:     $result .= "</span>\n<!-- end $dname date setting form -->\n";
1.10      matthew   536:     return $result;
                    537: }
                    538: 
1.175     raeburn   539: sub get_timedates {
                    540:     my ($epoch) = @_;
                    541:     my $dt = DateTime->from_epoch(epoch => $epoch)
                    542:                      ->set_time_zone(&Apache::lonlocal::gettimezone());
                    543:     my $tzname = $dt->time_zone_short_name();
                    544:     my $sec = $dt->second;
                    545:     my $min = $dt->minute;
                    546:     my $hour = $dt->hour;
                    547:     my $mday = $dt->day;
                    548:     my $month = $dt->month;
                    549:     if ($month) {
                    550:         $month --;
                    551:     }
                    552:     my $year = $dt->year;
                    553:     return ($tzname,$sec,$min,$hour,$mday,$month,$year);
                    554: }
1.166     banghart  555: 
                    556: sub build_url {
                    557:     my ($base, $fields)=@_;
                    558:     my $url;
                    559:     $url = $base.'?';
1.168     albertel  560:     foreach my $key (keys(%$fields)) {
                    561:         $url.=&escape($key).'='.&escape($$fields{$key}).'&amp;';
1.166     banghart  562:     }
                    563:     $url =~ s/&amp;$//;
                    564:     return $url;
                    565: }
                    566: 
                    567: 
1.10      matthew   568: ##############################################
                    569: ##############################################
                    570: 
1.22      matthew   571: =pod
                    572: 
1.10      matthew   573: =item &get_date_from_form
1.22      matthew   574: 
                    575: get_date_from_form retrieves the date specified in an &date_setter form.
1.10      matthew   576: 
                    577: Inputs:
                    578: 
                    579: =over 4
                    580: 
                    581: =item $dname
                    582: 
                    583: The name passed to &datesetter, which prefixes the form elements.
                    584: 
                    585: =item $defaulttime
                    586: 
                    587: The unix time to use as the default in case of poor inputs.
                    588: 
                    589: =back
                    590: 
                    591: Returns: Unix time represented in the form.
                    592: 
                    593: =cut
                    594: 
                    595: ##############################################
                    596: ##############################################
                    597: sub get_date_from_form {
                    598:     my ($dname) = @_;
                    599:     my ($sec,$min,$hour,$day,$month,$year);
                    600:     #
1.104     albertel  601:     if (defined($env{'form.'.$dname.'_second'})) {
                    602:         my $tmpsec = $env{'form.'.$dname.'_second'};
1.10      matthew   603:         if (($tmpsec =~ /^\d+$/) && ($tmpsec >= 0) && ($tmpsec < 60)) {
                    604:             $sec = $tmpsec;
                    605:         }
1.64      albertel  606: 	if (!defined($tmpsec) || $tmpsec eq '') { $sec = 0; }
1.67      matthew   607:     } else {
                    608:         $sec = 0;
1.10      matthew   609:     }
1.104     albertel  610:     if (defined($env{'form.'.$dname.'_minute'})) {
                    611:         my $tmpmin = $env{'form.'.$dname.'_minute'};
1.10      matthew   612:         if (($tmpmin =~ /^\d+$/) && ($tmpmin >= 0) && ($tmpmin < 60)) {
                    613:             $min = $tmpmin;
                    614:         }
1.64      albertel  615: 	if (!defined($tmpmin) || $tmpmin eq '') { $min = 0; }
1.67      matthew   616:     } else {
                    617:         $min = 0;
1.10      matthew   618:     }
1.104     albertel  619:     if (defined($env{'form.'.$dname.'_hour'})) {
                    620:         my $tmphour = $env{'form.'.$dname.'_hour'};
1.33      matthew   621:         if (($tmphour =~ /^\d+$/) && ($tmphour >= 0) && ($tmphour < 24)) {
1.10      matthew   622:             $hour = $tmphour;
                    623:         }
1.67      matthew   624:     } else {
                    625:         $hour = 0;
1.10      matthew   626:     }
1.104     albertel  627:     if (defined($env{'form.'.$dname.'_day'})) {
                    628:         my $tmpday = $env{'form.'.$dname.'_day'};
1.10      matthew   629:         if (($tmpday =~ /^\d+$/) && ($tmpday > 0) && ($tmpday < 32)) {
                    630:             $day = $tmpday;
                    631:         }
                    632:     }
1.104     albertel  633:     if (defined($env{'form.'.$dname.'_month'})) {
                    634:         my $tmpmonth = $env{'form.'.$dname.'_month'};
1.10      matthew   635:         if (($tmpmonth =~ /^\d+$/) && ($tmpmonth > 0) && ($tmpmonth < 13)) {
1.175     raeburn   636:             $month = $tmpmonth;
1.10      matthew   637:         }
                    638:     }
1.104     albertel  639:     if (defined($env{'form.'.$dname.'_year'})) {
                    640:         my $tmpyear = $env{'form.'.$dname.'_year'};
1.175     raeburn   641:         if (($tmpyear =~ /^\d+$/) && ($tmpyear >= 1970)) {
                    642:             $year = $tmpyear;
1.10      matthew   643:         }
                    644:     }
1.175     raeburn   645:     if (($year<1970) || ($year>2037)) { return undef; }
1.33      matthew   646:     if (defined($sec) && defined($min)   && defined($hour) &&
1.175     raeburn   647:         defined($day) && defined($month) && defined($year)) {
                    648:         my $timezone = &Apache::lonlocal::gettimezone();
                    649:         my $dt = DateTime->new( year   => $year,
                    650:                                 month  => $month,
                    651:                                 day    => $day,
                    652:                                 hour   => $hour,
                    653:                                 minute => $min,
                    654:                                 second => $sec,
                    655:                                 time_zone => $timezone,
                    656:                               );
                    657:         my $epoch_time  = $dt->epoch;
                    658:         if ($epoch_time ne '') {
                    659:             return $epoch_time;
                    660:         } else {
                    661:             return undef;
                    662:         }
1.10      matthew   663:     } else {
                    664:         return undef;
                    665:     }
1.20      matthew   666: }
                    667: 
                    668: ##############################################
                    669: ##############################################
                    670: 
                    671: =pod
                    672: 
                    673: =item &pjump_javascript_definition()
                    674: 
                    675: Returns javascript defining the 'pjump' function, which opens up a
                    676: parameter setting wizard.
                    677: 
                    678: =cut
                    679: 
                    680: ##############################################
                    681: ##############################################
                    682: sub pjump_javascript_definition {
                    683:     my $Str = <<END;
1.109     www       684:     function pjump(type,dis,value,marker,ret,call,hour,min,sec) {
1.20      matthew   685:         parmwin=window.open("/adm/rat/parameter.html?type="+escape(type)
                    686:                  +"&value="+escape(value)+"&marker="+escape(marker)
                    687:                  +"&return="+escape(ret)
1.109     www       688:                  +"&call="+escape(call)+"&name="+escape(dis)
                    689:                  +"&defhour="+escape(hour)+"&defmin="+escape(min)
                    690:                  +"&defsec="+escape(sec),"LONCAPAparms",
1.20      matthew   691:                  "height=350,width=350,scrollbars=no,menubar=no");
                    692:     }
                    693: END
                    694:     return $Str;
1.10      matthew   695: }
                    696: 
                    697: ##############################################
                    698: ##############################################
1.17      matthew   699: 
                    700: =pod
                    701: 
                    702: =item &javascript_nothing()
                    703: 
                    704: Return an appropriate null for the users browser.  This is used
                    705: as the first arguement for window.open calls when you want a blank
                    706: window that you can then write to.
                    707: 
                    708: =cut
                    709: 
                    710: ##############################################
                    711: ##############################################
                    712: sub javascript_nothing {
                    713:     # mozilla and other browsers work with "''", but IE on mac does not.
                    714:     my $nothing = "''";
                    715:     my $user_browser;
                    716:     my $user_os;
1.104     albertel  717:     $user_browser = $env{'browser.type'} if (exists($env{'browser.type'}));
                    718:     $user_os      = $env{'browser.os'}   if (exists($env{'browser.os'}));
1.17      matthew   719:     if (! defined($user_browser) || ! defined($user_os)) {
                    720:         (undef,$user_browser,undef,undef,undef,$user_os) = 
                    721:                            &Apache::loncommon::decode_user_agent();
                    722:     }
                    723:     if ($user_browser eq 'explorer' && $user_os =~ 'mac') {
                    724:         $nothing = "'javascript:void(0);'";
                    725:     }
                    726:     return $nothing;
                    727: }
                    728: 
1.90      www       729: ##############################################
                    730: ##############################################
                    731: sub javascript_docopen {
1.171     albertel  732:     my ($mimetype) = @_;
                    733:     $mimetype ||= 'text/html';
1.90      www       734:     # safari does not understand document.open() and loads "text/html"
                    735:     my $nothing = "''";
                    736:     my $user_browser;
                    737:     my $user_os;
1.104     albertel  738:     $user_browser = $env{'browser.type'} if (exists($env{'browser.type'}));
                    739:     $user_os      = $env{'browser.os'}   if (exists($env{'browser.os'}));
1.90      www       740:     if (! defined($user_browser) || ! defined($user_os)) {
                    741:         (undef,$user_browser,undef,undef,undef,$user_os) = 
                    742:                            &Apache::loncommon::decode_user_agent();
                    743:     }
                    744:     if ($user_browser eq 'safari' && $user_os =~ 'mac') {
                    745:         $nothing = "document.clear()";
                    746:     } else {
1.171     albertel  747: 	$nothing = "document.open('$mimetype','replace')";
1.90      www       748:     }
                    749:     return $nothing;
                    750: }
                    751: 
1.21      matthew   752: 
1.17      matthew   753: ##############################################
                    754: ##############################################
                    755: 
1.21      matthew   756: =pod
1.17      matthew   757: 
1.21      matthew   758: =item &StatusOptions()
1.10      matthew   759: 
1.21      matthew   760: Returns html for a selection box which allows the user to choose the
                    761: enrollment status of students.  The selection box name is 'Status'.
1.6       stredwic  762: 
1.21      matthew   763: Inputs:
1.6       stredwic  764: 
1.21      matthew   765: $status: the currently selected status.  If undefined the value of
1.104     albertel  766: $env{'form.Status'} is taken.  If that is undefined, a value of 'Active'
1.21      matthew   767: is used.
1.6       stredwic  768: 
1.21      matthew   769: $formname: The name of the form.  If defined the onchange attribute of
                    770: the selection box is set to document.$formname.submit().
1.6       stredwic  771: 
1.21      matthew   772: $size: the size (number of lines) of the selection box.
1.6       stredwic  773: 
1.27      matthew   774: $onchange: javascript to use when the value is changed.  Enclosed in 
                    775: double quotes, ""s, not single quotes.
                    776: 
1.21      matthew   777: Returns: a perl string as described.
1.1       stredwic  778: 
1.21      matthew   779: =cut
1.9       stredwic  780: 
1.21      matthew   781: ##############################################
                    782: ##############################################
                    783: sub StatusOptions {
1.165     banghart  784:     my ($status, $formName,$size,$onchange,$mult)=@_;
1.21      matthew   785:     $size = 1 if (!defined($size));
                    786:     if (! defined($status)) {
                    787:         $status = 'Active';
1.104     albertel  788:         $status = $env{'form.Status'} if (exists($env{'form.Status'}));
1.9       stredwic  789:     }
1.1       stredwic  790: 
                    791:     my $Str = '';
                    792:     $Str .= '<select name="Status"';
1.165     banghart  793:     if (defined($mult)){
                    794:         $Str .= ' multiple="multiple" ';
                    795:     }
1.27      matthew   796:     if(defined($formName) && $formName ne '' && ! defined($onchange)) {
1.1       stredwic  797:         $Str .= ' onchange="document.'.$formName.'.submit()"';
1.27      matthew   798:     }
                    799:     if (defined($onchange)) {
                    800:         $Str .= ' onchange="'.$onchange.'"';
1.1       stredwic  801:     }
1.21      matthew   802:     $Str .= ' size="'.$size.'" ';
1.1       stredwic  803:     $Str .= '>'."\n";
1.153     raeburn   804:     foreach my $type (['Active',  &mt('Currently Has Access')],
                    805: 		      ['Future',  &mt('Will Have Future Access')],
                    806: 		      ['Expired', &mt('Previously Had Access')],
                    807: 		      ['Any',     &mt('Any Access Status')]) {
1.151     albertel  808: 	my ($name,$label) = @$type;
                    809: 	$Str .= '<option value="'.$name.'" ';
                    810: 	if ($status eq $name) {
                    811: 	    $Str .= 'selected="selected" ';
                    812: 	}
                    813: 	$Str .= '>'.$label.'</option>'."\n";
                    814:     }
                    815: 
1.1       stredwic  816:     $Str .= '</select>'."\n";
1.7       stredwic  817: }
1.12      matthew   818: 
                    819: ########################################################
                    820: ########################################################
1.7       stredwic  821: 
1.23      matthew   822: =pod
                    823: 
                    824: =item Progess Window Handling Routines
                    825: 
                    826: These routines handle the creation, update, increment, and closure of 
                    827: progress windows.  The progress window reports to the user the number
                    828: of items completed and an estimate of the time required to complete the rest.
                    829: 
                    830: =over 4
                    831: 
                    832: 
                    833: =item &Create_PrgWin
                    834: 
                    835: Writes javascript to the client to open a progress window and returns a
                    836: data structure used for bookkeeping.
                    837: 
                    838: Inputs
                    839: 
                    840: =over 4
                    841: 
                    842: =item $r Apache request
                    843: 
                    844: =item $title The title of the progress window
                    845: 
                    846: =item $heading A description (usually 1 line) of the process being initiated.
                    847: 
                    848: =item $number_to_do The total number of items being processed.
1.50      albertel  849: 
                    850: =item $type Either 'popup' or 'inline' (popup is assumed if nothing is
                    851:        specified)
                    852: 
1.51      albertel  853: =item $width Specify the width in charaters of the input field.
                    854: 
1.50      albertel  855: =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
                    856: 
                    857: =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 
1.23      matthew   858: 
                    859: =back
                    860: 
                    861: Returns a hash containing the progress state data structure.
                    862: 
                    863: 
                    864: =item &Update_PrgWin
                    865: 
                    866: Updates the text in the progress indicator.  Does not increment the count.
                    867: See &Increment_PrgWin.
                    868: 
                    869: Inputs:
                    870: 
                    871: =over 4
                    872: 
                    873: =item $r Apache request
                    874: 
                    875: =item $prog_state Pointer to the data structure returned by &Create_PrgWin
                    876: 
                    877: =item $displaystring The string to write to the status indicator
                    878: 
                    879: =back
                    880: 
                    881: Returns: none
                    882: 
                    883: 
                    884: =item Increment_PrgWin
                    885: 
                    886: Increment the count of items completed for the progress window by 1.  
                    887: 
                    888: Inputs:
                    889: 
                    890: =over 4
                    891: 
                    892: =item $r Apache request
                    893: 
                    894: =item $prog_state Pointer to the data structure returned by Create_PrgWin
                    895: 
                    896: =item $extraInfo A description of the items being iterated over.  Typically
                    897: 'student'.
                    898: 
                    899: =back
                    900: 
                    901: Returns: none
                    902: 
                    903: 
                    904: =item Close_PrgWin
                    905: 
                    906: Closes the progress window.
                    907: 
                    908: Inputs:
                    909: 
                    910: =over 4 
                    911: 
                    912: =item $r Apache request
                    913: 
                    914: =item $prog_state Pointer to the data structure returned by Create_PrgWin
                    915: 
                    916: =back
                    917: 
                    918: Returns: none
                    919: 
                    920: =back
                    921: 
                    922: =cut
                    923: 
                    924: ########################################################
                    925: ########################################################
                    926: 
1.51      albertel  927: my $uniq=0;
                    928: sub get_uniq_name {
                    929:     $uniq++;
                    930:     return 'uniquename'.$uniq;
                    931: }
                    932: 
1.7       stredwic  933: # Create progress
                    934: sub Create_PrgWin {
1.51      albertel  935:     my ($r, $title, $heading, $number_to_do,$type,$width,$formname,
                    936: 	$inputname)=@_;
1.49      albertel  937:     if (!defined($type)) { $type='popup'; }
1.51      albertel  938:     if (!defined($width)) { $width=55; }
1.49      albertel  939:     my %prog_state;
                    940:     $prog_state{'type'}=$type;
                    941:     if ($type eq 'popup') {
                    942: 	$prog_state{'window'}='popwin';
1.122     albertel  943: 	my $start_page =
                    944: 	    &Apache::loncommon::start_page($title,undef,
                    945: 					   {'only_body' => 1,
                    946: 					    'bgcolor'   => '#88DDFF',
                    947: 					    'js_ready'  => 1});
                    948: 	my $end_page = &Apache::loncommon::end_page({'js_ready'  => 1});
                    949: 
1.49      albertel  950: 	#the whole function called through timeout is due to issues
                    951: 	#in mozilla Read BUG #2665 if you want to know the whole story
1.122     albertel  952: 	&r_print($r,'<script type="text/javascript">'.
1.49      albertel  953:         "var popwin;
                    954:          function openpopwin () {
                    955:          popwin=open(\'\',\'popwin\',\'width=400,height=100\');".
1.122     albertel  956:         "popwin.document.writeln(\'".$start_page.
1.170     albertel  957:               "<h4>".&mt("$heading")."<\/h4>".
1.159     banghart  958:               "<form action= \"\" name=\"popremain\" method=\"post\">".
1.51      albertel  959:               '<input type="text" size="'.$width.'" name="remaining" value="'.
1.131     albertel  960: 	      &mt('Starting').'" /><\\/form>'.$end_page.
1.122     albertel  961:               "\');".
1.49      albertel  962:         "popwin.document.close();}".
                    963:         "\nwindow.setTimeout(openpopwin,0)</script>");
                    964: 	$prog_state{'formname'}='popremain';
                    965: 	$prog_state{'inputname'}="remaining";
                    966:     } elsif ($type eq 'inline') {
                    967: 	$prog_state{'window'}='window';
                    968: 	if (!$formname) {
1.51      albertel  969: 	    $prog_state{'formname'}=&get_uniq_name();
1.159     banghart  970: 	    &r_print($r,'<form action="" name="'.$prog_state{'formname'}.'">');
1.49      albertel  971: 	} else {
                    972: 	    $prog_state{'formname'}=$formname;
                    973: 	}
                    974: 	if (!$inputname) {
1.51      albertel  975: 	    $prog_state{'inputname'}=&get_uniq_name();
1.170     albertel  976: 	    &r_print($r,&mt("$heading [_1]",' <input type="text" name="'.$prog_state{'inputname'}.'" size="'.$width.'" />'));
1.49      albertel  977: 	} else {
                    978: 	    $prog_state{'inputname'}=$inputname;
                    979: 	    
                    980: 	}
                    981: 	if (!$formname) { &r_print($r,'</form>'); }
                    982: 	&Update_PrgWin($r,\%prog_state,&mt('Starting'));
                    983:     }
1.7       stredwic  984: 
1.16      albertel  985:     $prog_state{'done'}=0;
1.23      matthew   986:     $prog_state{'firststart'}=&Time::HiRes::time();
                    987:     $prog_state{'laststart'}=&Time::HiRes::time();
1.16      albertel  988:     $prog_state{'max'}=$number_to_do;
1.49      albertel  989:     
1.14      albertel  990:     return %prog_state;
1.7       stredwic  991: }
                    992: 
                    993: # update progress
                    994: sub Update_PrgWin {
1.14      albertel  995:     my ($r,$prog_state,$displayString)=@_;
1.159     banghart  996:     &r_print($r,'<script type="text/javascript">'.$$prog_state{'window'}.'.document.'.
1.49      albertel  997: 	     $$prog_state{'formname'}.'.'.
                    998: 	     $$prog_state{'inputname'}.'.value="'.
1.48      albertel  999: 	     $displayString.'";</script>');
1.23      matthew  1000:     $$prog_state{'laststart'}=&Time::HiRes::time();
1.14      albertel 1001: }
                   1002: 
                   1003: # increment progress state
                   1004: sub Increment_PrgWin {
                   1005:     my ($r,$prog_state,$extraInfo)=@_;
1.16      albertel 1006:     $$prog_state{'done'}++;
1.23      matthew  1007:     my $time_est= (&Time::HiRes::time() - $$prog_state{'firststart'})/
                   1008:         $$prog_state{'done'} *
1.16      albertel 1009: 	($$prog_state{'max'}-$$prog_state{'done'});
                   1010:     $time_est = int($time_est);
1.80      matthew  1011:     #
                   1012:     my $min = int($time_est/60);
                   1013:     my $sec = $time_est % 60;
                   1014:     # 
                   1015:     my $str;
1.91      albertel 1016:     if ($min == 0 && $sec > 1) {
1.80      matthew  1017:         $str = '[_2] seconds';
1.91      albertel 1018:     } elsif ($min == 1 && $sec > 1) {
                   1019:         $str = '1 minute [_2] seconds';
1.80      matthew  1020:     } elsif ($min == 1 && $sec < 2) {
                   1021:         $str = '1 minute';
                   1022:     } elsif ($min < 10 && $sec > 1) {
                   1023:         $str = '[_1] minutes, [_2] seconds';
1.81      matthew  1024:     } elsif ($min >= 10 || $sec < 2) {
1.80      matthew  1025:         $str = '[_1] minutes';
1.16      albertel 1026:     }
1.80      matthew  1027:     $time_est = &mt($str,$min,$sec);
                   1028:     #
1.23      matthew  1029:     my $lasttime = &Time::HiRes::time()-$$prog_state{'laststart'};
                   1030:     if ($lasttime > 9) {
                   1031:         $lasttime = int($lasttime);
                   1032:     } elsif ($lasttime < 0.01) {
                   1033:         $lasttime = 0;
                   1034:     } else {
                   1035:         $lasttime = sprintf("%3.2f",$lasttime);
                   1036:     }
1.19      matthew  1037:     if ($lasttime == 1) {
1.32      www      1038:         $lasttime = '('.$lasttime.' '.&mt('second for').' '.$extraInfo.')';
1.19      matthew  1039:     } else {
1.32      www      1040:         $lasttime = '('.$lasttime.' '.&mt('seconds for').' '.$extraInfo.')';
1.28      matthew  1041:     }
                   1042:     #
1.104     albertel 1043:     my $user_browser = $env{'browser.type'} if (exists($env{'browser.type'}));
                   1044:     my $user_os      = $env{'browser.os'}   if (exists($env{'browser.os'}));
1.28      matthew  1045:     if (! defined($user_browser) || ! defined($user_os)) {
                   1046:         (undef,$user_browser,undef,undef,undef,$user_os) = 
                   1047:                            &Apache::loncommon::decode_user_agent();
                   1048:     }
                   1049:     if ($user_browser eq 'explorer' && $user_os =~ 'mac') {
                   1050:         $lasttime = '';
1.19      matthew  1051:     }
1.49      albertel 1052:     &r_print($r,'<script>'.$$prog_state{'window'}.'.document.'.
                   1053: 	     $$prog_state{'formname'}.'.'.
                   1054: 	     $$prog_state{'inputname'}.'.value="'.
1.48      albertel 1055: 	     $$prog_state{'done'}.'/'.$$prog_state{'max'}.
                   1056: 	     ': '.$time_est.' '.&mt('remaining').' '.$lasttime.'";'.'</script>');
1.23      matthew  1057:     $$prog_state{'laststart'}=&Time::HiRes::time();
1.7       stredwic 1058: }
                   1059: 
                   1060: # close Progress Line
                   1061: sub Close_PrgWin {
1.14      albertel 1062:     my ($r,$prog_state)=@_;
1.49      albertel 1063:     if ($$prog_state{'type'} eq 'popup') {
                   1064: 	&r_print($r,'<script>popwin.close()</script>'."\n");
                   1065:     } elsif ($$prog_state{'type'} eq 'inline') {
                   1066: 	&Update_PrgWin($r,$prog_state,&mt('Done'));
                   1067:     }
1.48      albertel 1068:     undef(%$prog_state);
                   1069: }
                   1070: 
                   1071: sub r_print {
                   1072:     my ($r,$to_print)=@_;
                   1073:     if ($r) {
                   1074: 	$r->print($to_print);
                   1075: 	$r->rflush();
1.47      sakharuk 1076:     } else {
1.48      albertel 1077: 	print($to_print);
1.47      sakharuk 1078:     }
1.1       stredwic 1079: }
1.34      www      1080: 
                   1081: # ------------------------------------------------------- Puts directory header
                   1082: 
                   1083: sub crumbs {
1.132     www      1084:     my ($uri,$target,$prefix,$form,$size,$noformat,$skiplast)=@_;
1.62      matthew  1085:     if (! defined($size)) {
                   1086:         $size = '+2';
                   1087:     }
1.100     raeburn  1088:     if ($target) {
                   1089:         $target = ' target="'.
                   1090:                   &Apache::loncommon::escape_single($target).'"';
                   1091:     }
1.78      www      1092:     my $output='';
                   1093:     unless ($noformat) { $output.='<br /><tt><b>'; }
                   1094:     $output.='<font size="'.$size.'">'.$prefix.'/';
1.182.2.2! raeburn  1095:     if (($env{'user.adv'}) || ($env{'user.author'})) {
1.43      www      1096: 	my $path=$prefix.'/';
1.99      matthew  1097: 	foreach my $dir (split('/',$uri)) {
                   1098:             if (! $dir) { next; }
                   1099:             $path .= $dir;
1.150     albertel 1100: 	    if ($path eq $uri) {
1.132     www      1101: 		if ($skiplast) {
                   1102: 		    $output.=$dir;
                   1103:                     last;
                   1104: 		} 
                   1105: 	    } else {
                   1106: 		$path.='/'; 
1.157     albertel 1107: 	    }	    
                   1108:             my $href_path = &HTML::Entities::encode($path,'<>&"');
1.160     albertel 1109: 	    &Apache::loncommon::inhibit_menu_check(\$href_path);
1.162     banghart 1110: 	    if ($form) {
                   1111: 	        my $href = 'javascript:'.$form.".action='".$href_path."';".$form.'.submit();';
                   1112: 	        $output.=qq{<a href="$href" $target>$dir</a>/};
                   1113: 	    } else {
                   1114: 	        $output.=qq{<a href="$href_path" $target>$dir</a>/};
                   1115: 	    }
1.35      www      1116: 	}
                   1117:     } else {
1.149     albertel 1118: 	foreach my $dir (split('/',$uri)) {
                   1119:             if (! $dir) { next; }
                   1120: 	    $output.=$dir.'/';
                   1121: 	}
1.34      www      1122:     }
1.149     albertel 1123:     if ($uri !~ m|/$|) { $output=~s|/$||; }
1.78      www      1124:     return $output.'</font>'.($noformat?'':'</b></tt><br />');
1.34      www      1125: }
                   1126: 
1.85      www      1127: # --------------------- A function that generates a window for the spellchecker
                   1128: 
                   1129: sub spellheader {
1.123     albertel 1130:     my $start_page=
                   1131: 	&Apache::loncommon::start_page('Speller Suggestions',undef,
1.140     albertel 1132: 				       {'only_body'   => 1,
                   1133: 					'js_ready'    => 1,
                   1134: 					'bgcolor'     => '#DDDDDD',
                   1135: 				        'add_entries' => {
                   1136: 					    'onload' => 
                   1137:                                                'document.forms.spellcheckform.submit()',
                   1138:                                              }
                   1139: 				        });
1.123     albertel 1140:     my $end_page=
                   1141: 	&Apache::loncommon::end_page({'js_ready'  => 1}); 
                   1142: 
1.105     www      1143:     my $nothing=&javascript_nothing();
1.85      www      1144:     return (<<ENDCHECK);
                   1145: <script type="text/javascript"> 
1.92      albertel 1146: //<!-- BEGIN LON-CAPA Internal
1.85      www      1147: var checkwin;
                   1148: 
1.140     albertel 1149: function spellcheckerwindow(string) {
                   1150:     var esc_string = string.replace(/\"/g,'&quot;');
1.105     www      1151:     checkwin=window.open($nothing,'spellcheckwin','height=320,width=280,resizable=yes,scrollbars=yes,location=no,menubar=no,toolbar=no');
1.154     albertel 1152:     checkwin.document.writeln('$start_page<form name="spellcheckform" action="/adm/spellcheck" method="post"><input type="hidden" name="text" value="'+esc_string+'" /><\\/form>$end_page');
1.85      www      1153:     checkwin.document.close();
                   1154: }
1.92      albertel 1155: // END LON-CAPA Internal -->
1.85      www      1156: </script>
                   1157: ENDCHECK
                   1158: }
                   1159: 
                   1160: # ---------------------------------- Generate link to spell checker for a field
                   1161: 
                   1162: sub spelllink {
                   1163:     my ($form,$field)=@_;
                   1164:     my $linktext=&mt('Check Spelling');
                   1165:     return (<<ENDLINK);
1.140     albertel 1166: <a href="javascript:if (typeof(document.$form.onsubmit)!='undefined') { if (document.$form.onsubmit!=null) { document.$form.onsubmit();}};spellcheckerwindow(this.document.forms.$form.$field.value);">$linktext</a>
1.85      www      1167: ENDLINK
                   1168: }
                   1169: 
1.52      www      1170: # ------------------------------------------------- Output headers for HTMLArea
                   1171: 
1.124     albertel 1172: {
                   1173:     my @htmlareafields;
                   1174:     sub init_htmlareafields {
                   1175: 	undef(@htmlareafields);
                   1176:     }
                   1177:     
                   1178:     sub add_htmlareafields {
                   1179: 	my (@newfields) = @_;
                   1180: 	push(@htmlareafields,@newfields);
                   1181:     }
                   1182: 
                   1183:     sub get_htmlareafields {
                   1184: 	return @htmlareafields;
                   1185:     }
                   1186: }
                   1187: 
1.52      www      1188: sub htmlareaheaders {
1.167     albertel 1189:     return if (&htmlareablocked());
                   1190:     return if (!&htmlareabrowser());
1.52      www      1191:     return (<<ENDHEADERS);
1.167     albertel 1192: <script type="text/javascript" src="/fckeditor/fckeditor.js"></script>
1.52      www      1193: ENDHEADERS
                   1194: }
                   1195: 
1.76      www      1196: # ----------------------------------------------------------------- Preferences
                   1197: 
                   1198: sub disablelink {
1.77      www      1199:     my @fields=@_;
                   1200:     if (defined($#fields)) {
                   1201: 	unless ($#fields>=0) { return ''; }
                   1202:     }
1.130     www      1203:     return '<a href="'.&HTML::Entities::encode('/adm/preferences?action=set_wysiwyg&wysiwyg=off&returnurl=','<>&"').&escape($ENV{'REQUEST_URI'}).'">'.&mt('Disable WYSIWYG Editor').'</a>';
1.76      www      1204: }
                   1205: 
                   1206: sub enablelink {
1.77      www      1207:     my @fields=@_;
                   1208:     if (defined($#fields)) {
                   1209: 	unless ($#fields>=0) { return ''; }
                   1210:     }
1.130     www      1211:     return '<a href="'.&HTML::Entities::encode('/adm/preferences?action=set_wysiwyg&wysiwyg=on&returnurl=','<>&"').&escape($ENV{'REQUEST_URI'}).'">'.&mt('Enable WYSIWYG Editor').'</a>';
1.76      www      1212: }
                   1213: 
1.167     albertel 1214: # ------------------------------------------------- lang to use in html editor
                   1215: sub htmlarea_lang {
                   1216:     my $lang='en';
                   1217:     if (&mt('htmlarea_lang') ne 'htmlarea_lang') {
                   1218: 	$lang=&mt('htmlarea_lang');
                   1219:     }
                   1220:     return $lang;
                   1221: }
                   1222: 
1.72      www      1223: # ----------------------------------------- Script to activate only some fields
                   1224: 
                   1225: sub htmlareaselectactive {
1.73      www      1226:     my @fields=@_;
1.76      www      1227:     unless (&htmlareabrowser()) { return ''; }
1.77      www      1228:     if (&htmlareablocked()) { return '<br />'.&enablelink(@fields); }
1.167     albertel 1229:     my $output='<script type="text/javascript" defer="1">';
                   1230:     my $lang = &htmlarea_lang();
                   1231:     foreach my $field (@fields) {
                   1232: 	$output.="
                   1233: {
                   1234:     var oFCKeditor = new FCKeditor('$field');
                   1235:     oFCKeditor.Config['CustomConfigurationsPath'] = 
                   1236: 	'/fckeditor/loncapaconfig.js';    
                   1237:     oFCKeditor.ReplaceTextarea();
                   1238:     oFCKeditor.Config['AutoDetectLanguage'] = false;
                   1239:     oFCKeditor.Config['DefaultLanguage'] = '$lang';
                   1240: }";
1.72      www      1241:     }
1.76      www      1242:     $output.="\nwindow.status='Activated Editfields';\n</script><br />".
1.77      www      1243: 	&disablelink(@fields);
1.72      www      1244:     return $output;
                   1245: }
                   1246: 
1.61      www      1247: # --------------------------------------------------------------------- Blocked
                   1248: 
                   1249: sub htmlareablocked {
1.104     albertel 1250:     unless ($env{'environment.wysiwygeditor'} eq 'on') { return 1; }
1.71      www      1251:     return 0;
1.52      www      1252: }
                   1253: 
                   1254: # ---------------------------------------- Browser capable of running HTMLArea?
                   1255: 
                   1256: sub htmlareabrowser {
                   1257:     return 1;
                   1258: }
1.53      matthew  1259: 
                   1260: ############################################################
                   1261: ############################################################
                   1262: 
                   1263: =pod
                   1264: 
                   1265: =item breadcrumbs
                   1266: 
                   1267: Compiles the previously registered breadcrumbs into an series of links.
                   1268: FAQ and BUG links will be placed on the left side of the table if they
                   1269: are defined for the last registered breadcrumb.  
                   1270: Additionally supports a 'component', which will be displayed on the
                   1271: right side of the table (without a link).
                   1272: A link to help for the component will be included if one is specified.
                   1273: 
                   1274: All inputs can be undef without problems.
                   1275: 
1.138     albertel 1276: Inputs: $component (the large text on the right side of the table),
1.53      matthew  1277:         $component_help
1.63      albertel 1278:         $menulink (boolean, controls whether to include a link to /adm/menu)
1.138     albertel 1279:         $helplink (if 'nohelp' don't include the orange help link)
                   1280:         $css_class (optional name for the class to apply to the table for CSS)
1.182.2.1  raeburn  1281:         $no_mt (optional flag, 1 if &mt() is _not_ to be applied to $component
                   1282:            when including the text on the right.
                   1283: 
1.53      matthew  1284: Returns a string containing breadcrumbs for the current page.
                   1285: 
                   1286: =item clear_breadcrumbs
                   1287: 
                   1288: Clears the previously stored breadcrumbs.
                   1289: 
                   1290: =item add_breadcrumb
                   1291: 
                   1292: Pushes a breadcrumb on the stack of crumbs.
                   1293: 
                   1294: input: $breadcrumb, a hash reference.  The keys 'href','title', and 'text'
                   1295: are required.  If present the keys 'faq' and 'bug' will be used to provide
1.156     albertel 1296: links to the FAQ and bug sites. If the key 'no_mt' is present the 'title' 
                   1297: and 'text' values won't be sent through &mt()
1.53      matthew  1298: 
                   1299: returns: nothing    
                   1300: 
                   1301: =cut
                   1302: 
                   1303: ############################################################
                   1304: ############################################################
                   1305: {
                   1306:     my @Crumbs;
1.57      matthew  1307:     
1.53      matthew  1308:     sub breadcrumbs {
1.182.2.1  raeburn  1309:         my ($component,$component_help,$menulink,$helplink,$css_class,$no_mt) = @_;
1.53      matthew  1310:         #
1.138     albertel 1311: 	$css_class ||= 'LC_breadcrumbs';
                   1312:         my $Str = "\n".'<table class="'.$css_class.'"><tr><td>';
1.57      matthew  1313:         #
                   1314:         # Make the faq and bug data cascade
                   1315:         my $faq = '';
                   1316:         my $bug = '';
1.106     www      1317: 	my $help='';
1.180     riegler  1318: 	# Crumb Symbol
                   1319: 	my $crumbsymbol = ' &#x25b6; ';
1.60      www      1320:         # The last breadcrumb does not have a link, so handle it separately.
1.53      matthew  1321:         my $last = pop(@Crumbs);
1.57      matthew  1322:         #
1.70      matthew  1323:         # The first one should be the course or a menu link
1.63      albertel 1324: 	if (!defined($menulink)) { $menulink=1; }
1.70      matthew  1325:         if ($menulink) {
                   1326:             my $description = 'Menu';
1.172     raeburn  1327:             my $no_mt_descr = 0;
1.104     albertel 1328:             if (exists($env{'request.course.id'}) && 
                   1329:                 $env{'request.course.id'} ne '') {
1.70      matthew  1330:                 $description = 
1.104     albertel 1331:                     $env{'course.'.$env{'request.course.id'}.'.description'};
1.172     raeburn  1332:                 $no_mt_descr = 1;
1.70      matthew  1333:             }
1.57      matthew  1334:             unshift(@Crumbs,{
1.70      matthew  1335:                     href   =>'/adm/menu',
                   1336:                     title  =>'Go to main menu',
                   1337:                     target =>'_top',
                   1338:                     text   =>$description,
1.172     raeburn  1339:                     no_mt  =>$no_mt_descr,
1.70      matthew  1340:                 });
1.53      matthew  1341:         }
                   1342:         my $links .= 
1.180     riegler  1343:             join($crumbsymbol,
1.53      matthew  1344:                  map {
1.57      matthew  1345:                      $faq = $_->{'faq'} if (exists($_->{'faq'}));
                   1346:                      $bug = $_->{'bug'} if (exists($_->{'bug'}));
1.106     www      1347:                      $help = $_->{'help'} if (exists($_->{'help'}));
1.69      matthew  1348:                      my $result = '<a href="'.$_->{'href'}.'" ';
                   1349:                      if (defined($_->{'target'}) && $_->{'target'} ne '') {
                   1350:                          $result .= 'target="'.$_->{'target'}.'" ';
                   1351:                      }
1.156     albertel 1352: 		     if ($_->{'no_mt'}) {
                   1353: 			 $result .='title="'.$_->{'title'}.'">'.
                   1354: 			     $_->{'text'}.'</a>';
                   1355: 		     } else {
                   1356: 			 $result .='title="'.&mt($_->{'title'}).'">'.
                   1357: 			     &mt($_->{'text'}).'</a>';
                   1358: 		     }
1.69      matthew  1359:                      $result;
1.53      matthew  1360:                      } @Crumbs
                   1361:                  );
1.180     riegler  1362:         $links .= $crumbsymbol if ($links ne '');
1.156     albertel 1363: 	if ($last->{'no_mt'}) {
                   1364: 	    $links .= '<b>'.$last->{'text'}.'</b>';
                   1365: 	} else {
                   1366: 	    $links .= '<b>'.&mt($last->{'text'}).'</b>';
                   1367: 	}
1.54      matthew  1368:         #
                   1369:         my $icons = '';
1.57      matthew  1370:         $faq = $last->{'faq'} if (exists($last->{'faq'}));
                   1371:         $bug = $last->{'bug'} if (exists($last->{'bug'}));
1.106     www      1372:         $help = $last->{'help'} if (exists($last->{'help'}));
                   1373:         $component_help=($component_help?$component_help:$help);
1.145     albertel 1374: #        if ($faq ne '') {
                   1375: #            $icons .= &Apache::loncommon::help_open_faq($faq);
                   1376: #        }
1.79      raeburn  1377: #        if ($bug ne '') {
                   1378: #            $icons .= &Apache::loncommon::help_open_bug($bug);
                   1379: #        }
1.144     albertel 1380: 	if ($faq ne '' || $component_help ne '' || $bug ne '') {
1.137     albertel 1381: 	    $icons .= &Apache::loncommon::help_open_menu($component,
1.126     albertel 1382: 							 $component_help,
1.137     albertel 1383: 							 $faq,$bug);
1.87      albertel 1384: 	}
1.54      matthew  1385:         #
1.126     albertel 1386:         $Str .= $links.'</td>';
1.54      matthew  1387:         #
1.53      matthew  1388:         if (defined($component)) {
1.182.2.1  raeburn  1389:             $Str .= '<td class="'.$css_class.'_component">';
                   1390:             if ($no_mt) {
                   1391:                 $Str .= $component;
                   1392:             } else {
                   1393:                 $Str .= &mt($component);
                   1394:             }
1.144     albertel 1395: 	    if ($icons ne '') {
                   1396: 		$Str .= '&nbsp;'.$icons;
                   1397: 	    }
                   1398: 	    $Str .= '</td>';
1.53      matthew  1399:         }
                   1400:         $Str .= '</tr></table>'."\n";
                   1401:         #
                   1402:         # Return the @Crumbs stack to what we started with
                   1403:         push(@Crumbs,$last);
                   1404:         shift(@Crumbs);
                   1405:         #
                   1406:         return $Str;
                   1407:     }
                   1408: 
                   1409:     sub clear_breadcrumbs {
                   1410:         undef(@Crumbs);
                   1411:     }
                   1412: 
                   1413:     sub add_breadcrumb {
                   1414:         push (@Crumbs,@_);
                   1415:     }
                   1416: 
1.57      matthew  1417: } # End of scope for @Crumbs
1.53      matthew  1418: 
                   1419: ############################################################
                   1420: ############################################################
                   1421: 
1.112     raeburn  1422: # Nested table routines.
                   1423: #
                   1424: # Routines to display form items in a multi-row table with 2 columns.
                   1425: # Uses nested tables to divide form elements into segments.
                   1426: # For examples of use see loncom/interface/lonnotify.pm 
                   1427: #
                   1428: # Can be used in following order: ...
                   1429: # &start_pick_box()
                   1430: # row1
                   1431: # row2
                   1432: # row3   ... etc.
1.173     raeburn  1433: # &submit_row()
1.161     raeburn  1434: # &end_pick_box()
1.112     raeburn  1435: #
                   1436: # where row1, row 2 etc. are chosen from &role_select_row,&course_select_row,
                   1437: # &status_select_row and &email_default_row
                   1438: #
                   1439: # Can also be used in following order:
                   1440: #
                   1441: # &start_pick_box()
                   1442: # &row_title()
                   1443: # &row_closure()
                   1444: # &row_title()
                   1445: # &row_closure()  ... etc.
                   1446: # &submit_row()
                   1447: # &end_pick_box()
                   1448: #
                   1449: # In general a &submit_row() call should proceed the call to &end_pick_box(),
                   1450: # as this routine adds a button for form submission.
1.113     raeburn  1451: # &submit_row() does not require a &row_closure after it.
1.112     raeburn  1452: #  
                   1453: # &start_pick_box() creates a bounding table with 1-pixel wide black border.
                   1454: # rows should be placed between calls to &start_pick_box() and &end_pick_box.
                   1455: #
                   1456: # &row_title() adds a title in the left column for each segment.
                   1457: # &row_closure() closes a row with a 1-pixel wide black line.
                   1458: #
                   1459: # &role_select_row() provides a select box from which to choose 1 or more roles 
                   1460: # &course_select_row provides ways of picking groups of courses
                   1461: #    radio buttons: all, by category or by picking from a course picker pop-up
                   1462: #      note: by category option is only displayed if a domain has implemented 
                   1463: #                selection by year, semester, department, number etc.
                   1464: #
                   1465: # &status_select_row() provides a select box from which to choose 1 or more
                   1466: #  access types (current access, prior access, and future access)  
                   1467: #
                   1468: # &email_default_row() provides text boxes for default e-mail suffixes for
                   1469: #  different authentication types in a domain.
                   1470: #
                   1471: # &row_title() and &row_closure() are called internally by the &*_select_row
                   1472: # routines, but can also be called directly to start and end rows which have 
                   1473: # needs that are not accommodated by the *_select_row() routines.    
                   1474: 
                   1475: sub start_pick_box {
1.142     albertel 1476:     my ($css_class) = @_;
                   1477:     if (defined($css_class)) {
                   1478: 	$css_class = 'class="'.$css_class.'"';
                   1479:     } else {
                   1480: 	$css_class= 'class="LC_pick_box"';
                   1481:     }
1.112     raeburn  1482:     my $output = <<"END";
1.142     albertel 1483:  <table $css_class>
1.112     raeburn  1484: END
                   1485:     return $output;
                   1486: }
                   1487: 
                   1488: sub end_pick_box {
                   1489:     my $output = <<"END";
                   1490:        </table>
                   1491: END
                   1492:     return $output;
                   1493: }
                   1494: 
1.181     bisitz   1495: sub row_headline {
                   1496:     my $output = <<"END";
                   1497:            <tr><td colspan="2">
                   1498: END
                   1499:     return $output;
                   1500: }
                   1501: 
1.112     raeburn  1502: sub row_title {
1.142     albertel 1503:     my ($title,$css_title_class,$css_value_class) = @_;
                   1504:     $css_title_class ||= 'LC_pick_box_title';
                   1505:     $css_title_class = 'class="'.$css_title_class.'"';
                   1506: 
                   1507:     $css_value_class ||= 'LC_pick_box_value';
                   1508:     $css_value_class = 'class="'.$css_value_class.'"';
                   1509: 
1.173     raeburn  1510:     if ($title ne '') {
                   1511:         $title .= ':';
                   1512:     }
1.112     raeburn  1513:     my $output = <<"ENDONE";
1.142     albertel 1514:            <tr class="LC_pick_box_row">
                   1515:             <td $css_title_class>
1.173     raeburn  1516: 	       $title
1.112     raeburn  1517:             </td>
1.142     albertel 1518:             <td $css_value_class>
1.112     raeburn  1519: ENDONE
                   1520:     return $output;
                   1521: }
                   1522: 
                   1523: sub row_closure {
1.143     albertel 1524:     my ($no_separator) =@_;
1.113     raeburn  1525:     my $output = <<"ENDTWO";
1.112     raeburn  1526:             </td>
                   1527:            </tr>
1.143     albertel 1528: ENDTWO
                   1529:     if (!$no_separator) {
                   1530:         $output .= <<"ENDTWO";
1.112     raeburn  1531:            <tr>
1.143     albertel 1532:             <td colspan="2" class="LC_pick_box_separator">
1.112     raeburn  1533:             </td>
                   1534:            </tr>
                   1535: ENDTWO
1.143     albertel 1536:     }
1.112     raeburn  1537:     return $output;
                   1538: }
                   1539: 
                   1540: sub role_select_row {
1.147     raeburn  1541:     my ($roles,$title,$css_class,$show_separate_custom,$cdom,$cnum) = @_;
1.116     raeburn  1542:     my $output;
                   1543:     if (defined($title)) {
1.142     albertel 1544:         $output = &row_title($title,$css_class);
1.116     raeburn  1545:     }
1.142     albertel 1546:     $output .= qq|
1.112     raeburn  1547:                                   <select name="roles" multiple >\n|;
1.113     raeburn  1548:     foreach my $role (@$roles) {
1.114     raeburn  1549:         my $plrole;
                   1550:         if ($role eq 'ow') {
                   1551:             $plrole = &mt('Course Owner');
1.147     raeburn  1552:         } elsif ($role eq 'cr') {
                   1553:             if ($show_separate_custom) {
                   1554:                 if ($cdom ne '' && $cnum ne '') {
                   1555:                     my %course_customroles = &course_custom_roles($cdom,$cnum);
                   1556:                     foreach my $crrole (sort(keys(%course_customroles))) {
                   1557:                         my ($plcrrole) = ($crrole =~ m|^cr/[^/]+/[^/]+/(.+)$|);
                   1558:                         $output .= '  <option value="'.$crrole.'">'.$plcrrole.
                   1559:                                    '</option>';
                   1560:                     }
                   1561:                 }
                   1562:             } else {
                   1563:                 $plrole = &mt('Custom Role');
                   1564:             }
1.114     raeburn  1565:         } else {
                   1566:             $plrole=&Apache::lonnet::plaintext($role);
                   1567:         }
1.147     raeburn  1568:         if (($role ne 'cr') || (!$show_separate_custom)) {
                   1569:             $output .= '  <option value="'.$role.'">'.$plrole.'</option>';
                   1570:         }
1.112     raeburn  1571:     }
1.142     albertel 1572:     $output .= qq|                </select>\n|;
1.116     raeburn  1573:     if (defined($title)) {
                   1574:         $output .= &row_closure();
                   1575:     }
1.112     raeburn  1576:     return $output;
                   1577: }
                   1578: 
                   1579: sub course_select_row {
1.142     albertel 1580:     my ($title,$formname,$totcodes,$codetitles,$idlist,$idlist_titles,
                   1581: 	$css_class) = @_;
                   1582:     my $output = &row_title($title,$css_class);
1.169     raeburn  1583:     $output .= &course_selection($formname,$totcodes,$codetitles,$idlist,$idlist_titles);
                   1584:     $output .= &row_closure();
                   1585:     return $output;
                   1586: }
                   1587: 
                   1588: sub course_selection {
                   1589:     my ($formname,$totcodes,$codetitles,$idlist,$idlist_titles) = @_;
                   1590:     my $output = qq|
1.142     albertel 1591: <script type="text/javascript">
1.112     raeburn  1592:     function coursePick (formname) {
                   1593:         for  (var i=0; i<formname.coursepick.length; i++) {
1.114     raeburn  1594:             if (formname.coursepick[i].value == 'category') {
                   1595:                 courseSet('');
                   1596:             }
1.112     raeburn  1597:             if (!formname.coursepick[i].checked) {
                   1598:                 if (formname.coursepick[i].value == 'specific') {
                   1599:                     formname.coursetotal.value = 0;
                   1600:                     formname.courselist = '';
                   1601:                 }
                   1602:             }
                   1603:         }
                   1604:     }
1.114     raeburn  1605:     function setPick (formname) {
                   1606:         for  (var i=0; i<formname.coursepick.length; i++) {
                   1607:             if (formname.coursepick[i].value == 'category') {
                   1608:                 formname.coursepick[i].checked = true;
                   1609:             }
                   1610:             formname.coursetotal.value = 0;
                   1611:             formname.courselist = '';
                   1612:         }
                   1613:     }
1.112     raeburn  1614: </script>
                   1615:     |;
                   1616:     my $courseform='<b>'.&Apache::loncommon::selectcourse_link
1.118     raeburn  1617:                      ($formname,'pickcourse','pickdomain','coursedesc','',1).'</b>';
1.129     raeburn  1618:         $output .= '<input type="radio" name="coursepick" value="all" onclick="coursePick(this.form)" />'.&mt('All courses').'<br />';
1.112     raeburn  1619:     if ($totcodes > 0) {
                   1620:         my $numtitles = @$codetitles;
                   1621:         if ($numtitles > 0) {
1.129     raeburn  1622:             $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 />';
1.112     raeburn  1623:             $output .= '<table><tr><td>'.$$codetitles[0].'<br />'."\n".
                   1624:                '<select name="'.$$codetitles[0].
1.114     raeburn  1625:                '" onChange="setPick(this.form);courseSet('."'$$codetitles[0]'".')">'."\n".
1.112     raeburn  1626:                ' <option value="-1" />Select'."\n";
                   1627:             my @items = ();
                   1628:             my @longitems = ();
                   1629:             if ($$idlist{$$codetitles[0]} =~ /","/) {
1.113     raeburn  1630:                 @items = split(/","/,$$idlist{$$codetitles[0]});
1.112     raeburn  1631:             } else {
                   1632:                 $items[0] = $$idlist{$$codetitles[0]};
                   1633:             }
                   1634:             if (defined($$idlist_titles{$$codetitles[0]})) {
                   1635:                 if ($$idlist_titles{$$codetitles[0]} =~ /","/) {
1.113     raeburn  1636:                     @longitems = split(/","/,$$idlist_titles{$$codetitles[0]});
1.112     raeburn  1637:                 } else {
                   1638:                     $longitems[0] = $$idlist_titles{$$codetitles[0]};
                   1639:                 }
                   1640:                 for (my $i=0; $i<@longitems; $i++) {
                   1641:                     if ($longitems[$i] eq '') {
                   1642:                         $longitems[$i] = $items[$i];
                   1643:                     }
                   1644:                 }
                   1645:             } else {
                   1646:                 @longitems = @items;
                   1647:             }
                   1648:             for (my $i=0; $i<@items; $i++) {
                   1649:                 $output .= ' <option value="'.$items[$i].'">'.$longitems[$i].'</option>';
                   1650:             }
                   1651:             $output .= '</select></td>';
                   1652:             for (my $i=1; $i<$numtitles; $i++) {
                   1653:                 $output .= '<td>'.$$codetitles[$i].'<br />'."\n".
                   1654:                           '<select name="'.$$codetitles[$i].
                   1655:                           '" onChange="courseSet('."'$$codetitles[$i]'".')">'."\n".
                   1656:                           '<option value="-1">&lt;-Pick '.$$codetitles[$i-1].'</option>'."\n".
                   1657:                           '</select>'."\n".
                   1658:                           '</td>';
                   1659:             }
                   1660:             $output .= '</tr></table><br />';
                   1661:         }
                   1662:     }
1.169     raeburn  1663:     $output .= '<input type="radio" name="coursepick" value="specific" onclick="coursePick(this.form);opencrsbrowser('."'".$formname."','dccourse','dcdomain','coursedesc','','1'".')" />'.&mt('Pick specific course(s):').' '.$courseform.'&nbsp;&nbsp;<input type="text" value="0" size="4" name="coursetotal" /><input type="hidden" name="courselist" value="" />selected.<br />'."\n";
1.112     raeburn  1664:     return $output;
                   1665: }
                   1666: 
                   1667: sub status_select_row {
1.142     albertel 1668:     my ($types,$title,$css_class) = @_;
1.117     raeburn  1669:     my $output; 
                   1670:     if (defined($title)) {
1.142     albertel 1671:         $output = &row_title($title,$css_class,'LC_pick_box_select');
1.117     raeburn  1672:     }
1.142     albertel 1673:     $output .= qq|
1.112     raeburn  1674:                                     <select name="types" multiple>\n|;
1.113     raeburn  1675:     foreach my $status_type (sort(keys(%{$types}))) {
1.112     raeburn  1676:         $output .= '  <option value="'.$status_type.'">'.$$types{$status_type}.'</option>';
                   1677:     }
1.142     albertel 1678:     $output .= qq|                   </select>\n|; 
1.117     raeburn  1679:     if (defined($title)) {
                   1680:         $output .= &row_closure();
                   1681:     }
1.112     raeburn  1682:     return $output;
                   1683: }
                   1684: 
                   1685: sub email_default_row {
1.142     albertel 1686:     my ($authtypes,$title,$descrip,$css_class) = @_;
                   1687:     my $output = &row_title($title,$css_class);
                   1688:     $output .= $descrip.
                   1689: 	&Apache::loncommon::start_data_table().
                   1690: 	&Apache::loncommon::start_data_table_header_row().
                   1691: 	'<th>'.&mt('Authentication Method').'</th>'.
                   1692: 	'<th align="right">'.&mt('Username -> e-mail conversion').'</th>'."\n".
                   1693: 	&Apache::loncommon::end_data_table_header_row();
1.112     raeburn  1694:     my $rownum = 0;
1.113     raeburn  1695:     foreach my $auth (sort(keys(%{$authtypes}))) {
1.112     raeburn  1696:         my ($userentry,$size);
                   1697:         if ($auth =~ /^krb/) {
                   1698:             $userentry = '';
                   1699:             $size = 25;
                   1700:         } else {
                   1701:             $userentry = 'username@';
                   1702:             $size = 15;
                   1703:         }
1.142     albertel 1704:         $output .= &Apache::loncommon::start_data_table_row().
                   1705: 	    '<td>  '.$$authtypes{$auth}.'</td>'.
                   1706: 	    '<td align="right">'.$userentry.
                   1707: 	    '<input type="text" name="'.$auth.'" size="'.$size.'" /></td>'.
                   1708: 	    &Apache::loncommon::end_data_table_row();
1.112     raeburn  1709:     }
1.142     albertel 1710:     $output .= &Apache::loncommon::end_data_table();
1.112     raeburn  1711:     $output .= &row_closure();
                   1712:     return $output;
                   1713: }
                   1714: 
                   1715: 
                   1716: sub submit_row {
1.142     albertel 1717:     my ($title,$cmd,$submit_text,$css_class) = @_;
                   1718:     my $output = &row_title($title,$css_class,'LC_pick_box_submit');
1.112     raeburn  1719:     $output .= qq|
                   1720:              <br />
                   1721:              <input type="hidden" name="command" value="$cmd" />
                   1722:              <input type="submit" value="$submit_text"/> &nbsp;
                   1723:              <br /><br />
1.142     albertel 1724:             \n|;
1.112     raeburn  1725:     return $output;
                   1726: }
1.1       stredwic 1727: 
1.147     raeburn  1728: sub course_custom_roles {
                   1729:     my ($cdom,$cnum) = @_;
                   1730:     my %returnhash=();
                   1731:     my %coursepersonnel=&Apache::lonnet::dump('nohist_userroles',$cdom,$cnum);
                   1732:     foreach my $person (sort(keys(%coursepersonnel))) {
                   1733:         my ($role) = ($person =~ /^([^:]+):/);
                   1734:         my ($end,$start) = split(/:/,$coursepersonnel{$person});
                   1735:         if ($end == -1 && $start == -1) {
                   1736:             next;
                   1737:         }
                   1738:         if ($role =~ m|^cr/[^/]+/[^/]+/[^/]|) {
                   1739:             $returnhash{$role} ++;
                   1740:         }
                   1741:     }
                   1742:     return %returnhash;
                   1743: }
                   1744: 
                   1745: 
1.119     raeburn  1746: ##############################################
                   1747: ##############################################
1.179     raeburn  1748: 
                   1749: # topic_bar
                   1750: #
                   1751: # Generates a div containing a numbered (static image) followed by a title
                   1752: # with a background color defined in the corresponding CSS: LC_topic_bar
                   1753: #
                   1754: sub topic_bar {
                   1755:     my ($imgnum,$title) = @_;
                   1756:     return '
                   1757: <div class="LC_topic_bar">
                   1758:     <img alt="'.&mt('Step [_1]',$imgnum).
                   1759:               '"src="/res/adm/pages/bl_step'.$imgnum.'.gif" />&nbsp;
                   1760:     <span>'.$title.'</span>
                   1761: </div>
                   1762: ';
                   1763: }
                   1764: 
                   1765: ##############################################
                   1766: ##############################################
1.119     raeburn  1767:                                                                              
                   1768: # echo_form_input
                   1769: #
                   1770: # Generates html markup to add form elements from the referrer page
                   1771: # as hidden form elements (values encoded) in the new page.
                   1772: #
                   1773: # Intended to support two types of use 
                   1774: # (a) to allow backing up to earlier pages in a multi-page 
                   1775: # form submission process using a breadcrumb trail.
                   1776: #
                   1777: # (b) to allow the current page to be reloaded with form elements
                   1778: # set on previous page to remain unchanged.  An example would
                   1779: # be where the a page containing a dynamically-built table of data is 
                   1780: # is to be redisplayed, with only the sort order of the data changed. 
                   1781: #  
                   1782: # Inputs:
                   1783: # 1. Reference to array of form elements in the submitted form on 
                   1784: # the referrer page which are to be excluded from the echoed elements.
                   1785: #
                   1786: # 2. Reference to array of regular expressions, which if matched in the  
                   1787: # name of the form element n the referrer page will be omitted from echo. 
                   1788: #
                   1789: # Outputs: A scalar containing the html markup for the echoed form
                   1790: # elements (all as hidden elements, with values encoded). 
                   1791: 
                   1792: 
                   1793: sub echo_form_input {
                   1794:     my ($excluded,$regexps) = @_;
                   1795:     my $output = '';
                   1796:     foreach my $key (keys(%env)) {
                   1797:         if ($key =~ /^form\.(.+)$/) {
                   1798:             my $name = $1;
                   1799:             my $match = 0;
                   1800:             if ((!@{$excluded}) || (!grep/^$name$/,@{$excluded})) {
                   1801:                 if (defined($regexps)) {
                   1802:                     if (@{$regexps} > 0) {
                   1803:                         foreach my $regexp (@{$regexps}) {
                   1804:                             if ($name =~ /\Q$regexp\E/) {
                   1805:                                 $match = 1;
                   1806:                                 last;
                   1807:                             }
                   1808:                         }
                   1809:                     }
                   1810:                 }
                   1811:                 if (!$match) {
                   1812:                     if (ref($env{$key})) {
                   1813:                         foreach my $value (@{$env{$key}}) {
                   1814:                             $value = &HTML::Entities::encode($value,'<>&"');
                   1815:                             $output .= '<input type="hidden" name="'.$name.
                   1816:                                              '" value="'.$value.'" />'."\n";
                   1817:                         }
                   1818:                     } else {
                   1819:                         my $value = &HTML::Entities::encode($env{$key},'<>&"');
                   1820:                         $output .= '<input type="hidden" name="'.$name.
                   1821:                                              '" value="'.$value.'" />'."\n";
                   1822:                     }
                   1823:                 }
                   1824:             }
                   1825:         }
                   1826:     }
                   1827:     return $output;
                   1828: }
                   1829: 
                   1830: ##############################################
                   1831: ##############################################
                   1832:                                                                              
                   1833: # set_form_elements
                   1834: #
                   1835: # Generates javascript to set form elements to values based on
                   1836: # corresponding values for the same form elements when the page was
                   1837: # previously submitted.
                   1838: #     
                   1839: # Last submission values are read from hidden form elements in referring 
                   1840: # page which have the same name, i.e., generated by &echo_form_input(). 
                   1841: #
                   1842: # Intended to be called by onload event.
                   1843: #
1.121     raeburn  1844: # Inputs:
                   1845: # (a) Reference to hash of echoed form elements to be set.
1.119     raeburn  1846: #
                   1847: # In the hash, keys are the form element names, and the values are the
                   1848: # element type (selectbox, radio, checkbox or text -for textbox, textarea or
                   1849: # hidden).
1.121     raeburn  1850: #
                   1851: # (b) Optional reference to hash of stored elements to be set.
                   1852: #
                   1853: # If the page being displayed is a page which permits modification of
                   1854: # previously stored data, e.g., the first page in a multi-page submission,
                   1855: # then if stored is supplied, form elements will be set to the last stored
                   1856: # values.  If user supplied values are also available for the same elements
                   1857: # these will replace the stored values. 
                   1858: #        
1.119     raeburn  1859: # Output:
                   1860: #  
                   1861: # javascript function - set_form_elements() which sets form elements,
                   1862: # expects an argument: formname - the name of the form according to 
                   1863: # the DOM, e.g., document.compose
                   1864: 
                   1865: sub set_form_elements {
1.121     raeburn  1866:     my ($elements,$stored) = @_;
                   1867:     my %values;
1.119     raeburn  1868:     my $output .= 'function setFormElements(courseForm) {
1.121     raeburn  1869: ';
                   1870:     if (defined($stored)) {
                   1871:         foreach my $name (keys(%{$stored})) {
                   1872:             if (exists($$elements{$name})) {
                   1873:                 if (ref($$stored{$name}) eq 'ARRAY') {
                   1874:                     $values{$name} = $$stored{$name};
                   1875:                 } else {
                   1876:                     @{$values{$name}} = ($$stored{$name});
                   1877:                 }
                   1878:             }
                   1879:         }
                   1880:     }
                   1881: 
1.119     raeburn  1882:     foreach my $key (keys(%env)) {
                   1883:         if ($key =~ /^form\.(.+)$/) {
                   1884:             my $name = $1;
                   1885:             if (exists($$elements{$name})) {
1.121     raeburn  1886:                 @{$values{$name}} = &Apache::loncommon::get_env_multiple($key);
                   1887:             }
                   1888:         }
                   1889:     }
                   1890: 
                   1891:     foreach my $name (keys(%values)) {
                   1892:         for (my $i=0; $i<@{$values{$name}}; $i++) {
                   1893:             $values{$name}[$i] = &HTML::Entities::decode($values{$name}[$i],'<>&"');
                   1894:             $values{$name}[$i] =~ s/([\r\n\f]+)/\\n/g;
                   1895:             $values{$name}[$i] =~ s/"/\\"/g;
                   1896:         }
                   1897:         if ($$elements{$name} eq 'text') {
                   1898:             my $numvalues = @{$values{$name}};
                   1899:             if ($numvalues > 1) {
                   1900:                 my $valuestring = join('","',@{$values{$name}});
                   1901:                 $output .= qq|
1.119     raeburn  1902:   var textvalues = new Array ("$valuestring");
1.147     raeburn  1903:   var total = courseForm.elements['$name'].length;
1.119     raeburn  1904:   if (total > $numvalues) {
                   1905:       total = $numvalues;
                   1906:   }    
                   1907:   for (var i=0; i<total; i++) {
1.147     raeburn  1908:       courseForm.elements['$name']\[i].value = textvalues[i];
1.119     raeburn  1909:   }
                   1910: |;
1.121     raeburn  1911:             } else {
                   1912:                 $output .= qq|
1.147     raeburn  1913:   courseForm.elements['$name'].value = "$values{$name}[0]";
1.119     raeburn  1914: |;
1.121     raeburn  1915:             }
                   1916:         } else {
                   1917:             $output .=  qq|
1.147     raeburn  1918:   var elementLength = courseForm.elements['$name'].length;
1.119     raeburn  1919:   if (elementLength==undefined) {
                   1920: |;
1.121     raeburn  1921:             foreach my $value (@{$values{$name}}) {
                   1922:                 if ($$elements{$name} eq 'selectbox') {
                   1923:                     $output .=  qq|
1.147     raeburn  1924:       if (courseForm.elements['$name'].options[0].value == "$value") {
                   1925:           courseForm.elements['$name'].options[0].selected = true;
1.119     raeburn  1926:       }|;
1.121     raeburn  1927:                 } elsif (($$elements{$name} eq 'radio') ||
                   1928:                          ($$elements{$name} eq 'checkbox')) {
                   1929:                     $output .= qq|
1.147     raeburn  1930:       if (courseForm.elements['$name'].value == "$value") {
1.148     albertel 1931:           courseForm.elements['$name'].checked = true;
1.119     raeburn  1932:       }|;
1.121     raeburn  1933:                 }
                   1934:             }
                   1935:             $output .= qq|
1.119     raeburn  1936:   }
                   1937:   else {
1.147     raeburn  1938:       for (var i=0; i<courseForm.elements['$name'].length; i++) {
1.119     raeburn  1939: |;
1.121     raeburn  1940:             if ($$elements{$name} eq 'selectbox') {
                   1941:                 $output .=  qq|
1.147     raeburn  1942:           courseForm.elements['$name'].options[i].selected = false;|;
1.121     raeburn  1943:             } elsif (($$elements{$name} eq 'radio') || 
                   1944:                      ($$elements{$name} eq 'checkbox')) {
                   1945:                 $output .= qq|
1.147     raeburn  1946:           courseForm.elements['$name']\[i].checked = false;|; 
1.121     raeburn  1947:             }
                   1948:             $output .= qq|
1.119     raeburn  1949:       }
1.147     raeburn  1950:       for (var j=0; j<courseForm.elements['$name'].length; j++) {
1.119     raeburn  1951: |;
1.121     raeburn  1952:             foreach my $value (@{$values{$name}}) {
                   1953:                 if ($$elements{$name} eq 'selectbox') {
                   1954:                     $output .=  qq|
1.147     raeburn  1955:           if (courseForm.elements['$name'].options[j].value == "$value") {
                   1956:               courseForm.elements['$name'].options[j].selected = true;
1.119     raeburn  1957:           }|;
1.121     raeburn  1958:                 } elsif (($$elements{$name} eq 'radio') ||
                   1959:                          ($$elements{$name} eq 'checkbox')) { 
                   1960:                       $output .= qq|
1.147     raeburn  1961:           if (courseForm.elements['$name']\[j].value == "$value") {
                   1962:               courseForm.elements['$name']\[j].checked = true;
1.119     raeburn  1963:           }|;
1.121     raeburn  1964:                 }
                   1965:             }
                   1966:             $output .= qq|
1.119     raeburn  1967:       }
                   1968:   }
                   1969: |;
                   1970:         }
                   1971:     }
                   1972:     $output .= "
                   1973: }\n";
                   1974:     return $output;
                   1975: }
                   1976: 
1.158     raeburn  1977: ##############################################
                   1978: ##############################################
                   1979: 
                   1980: # javascript_valid_email
                   1981: #
                   1982: # Generates javascript to validate an e-mail address.
                   1983: # Returns a javascript function which accetps a form field as argumnent, and
                   1984: # returns false if field.value does not satisfy two regular expression matches
                   1985: # for a valid e-mail address.  Backwards compatible with old browsers without
                   1986: # support for javascript RegExp (just checks for @ in field.value in this case). 
                   1987: 
                   1988: sub javascript_valid_email {
                   1989:     my $scripttag .= <<'END';
                   1990: function validmail(field) {
                   1991:     var str = field.value;
                   1992:     if (window.RegExp) {
                   1993:         var reg1str = "(@.*@)|(\\.\\.)|(@\\.)|(\\.@)|(^\\.)";
                   1994:         var reg2str = "^.+\\@(\\[?)[a-zA-Z0-9\\-\\.]+\\.([a-zA-Z]{2,3}|[0-9]{1,3})(\\]?)$"; //"
                   1995:         var reg1 = new RegExp(reg1str);
                   1996:         var reg2 = new RegExp(reg2str);
                   1997:         if (!reg1.test(str) && reg2.test(str)) {
                   1998:             return true;
                   1999:         }
                   2000:         return false;
                   2001:     }
                   2002:     else
                   2003:     {
                   2004:         if(str.indexOf("@") >= 0) {
                   2005:             return true;
                   2006:         }
                   2007:         return false;
                   2008:     }
                   2009: }
                   2010: END
                   2011:     return $scripttag;
                   2012: }
                   2013: 
1.176     foxr     2014: 
                   2015: 
1.1       stredwic 2016: 1;
1.23      matthew  2017: 
1.1       stredwic 2018: __END__

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>
500 Internal Server Error

Internal Server Error

The server encountered an internal error or misconfiguration and was unable to complete your request.

Please contact the server administrator at root@localhost to inform them of the time this error occurred, and the actions you performed just before this error.

More information about this error may be available in the server error log.