--- loncom/interface/lonhtmlcommon.pm 2003/03/03 22:00:03 1.15 +++ loncom/interface/lonhtmlcommon.pm 2004/05/10 18:57:43 1.70 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # a pile of common html routines # -# $Id: lonhtmlcommon.pm,v 1.15 2003/03/03 22:00:03 albertel Exp $ +# $Id: lonhtmlcommon.pm,v 1.70 2004/05/10 18:57:43 matthew Exp $ # # Copyright Michigan State University Board of Trustees # @@ -56,6 +56,8 @@ html. package Apache::lonhtmlcommon; use Time::Local; +use Time::HiRes; +use Apache::lonlocal; use strict; ############################################## @@ -63,8 +65,126 @@ use strict; =pod +=item authorbombs + +=cut + +############################################## +############################################## + +sub authorbombs { + my $url=shift; + $url=&Apache::lonnet::declutter($url); + my ($udom,$uname)=($url=~/^(\w+)\/(\w+)\//); + my %bombs=&Apache::lonmsg::all_url_author_res_msg($uname,$udom); + foreach (keys %bombs) { + if ($_=~/^$udom\/$uname\//) { + return ''. + &Apache::loncommon::help_open_topic('About_Bombs'); + } + } + return ''; +} + +############################################## +############################################## + +sub recent_filename { + my $area=shift; + return 'nohist_recent_'.&Apache::lonnet::escape($area); +} + +sub store_recent { + my ($area,$name,$value)=@_; + my $file=&recent_filename($area); + my %recent=&Apache::lonnet::dump($file); + if (scalar(keys(%recent))>10) { +# remove oldest value + my $oldest=time; + my $delkey=''; + foreach (keys %recent) { + my $thistime=(split(/\&/,$recent{$_}))[0]; + if ($thistime<$oldest) { + $oldest=$thistime; + $delkey=$_; + } + } + &Apache::lonnet::del($file,[$delkey]); + } +# store new value + &Apache::lonnet::put($file,{ $name => + time.'&'.&Apache::lonnet::escape($value) }); +} + +sub select_recent { + my ($area,$fieldname,$event)=@_; + my %recent=&Apache::lonnet::dump(&recent_filename($area)); + my $return="\n\n"; + return $return; +} + + +=pod + +=item textbox + +=cut + +############################################## +############################################## +sub textbox { + my ($name,$value,$size,$special) = @_; + $size = 40 if (! defined($size)); + my $Str = ''; + return $Str; +} + +############################################## +############################################## + +=pod + +=item checkbox + +=cut + +############################################## +############################################## +sub checkbox { + my ($name,$checked,$value) = @_; + my $Str = ' @@ -128,57 +280,108 @@ sub date_setter { document.$formname.$dname\_day.value = 30; } } + + function $dname\_disable() { + document.$formname.$dname\_month.disabled=true; + document.$formname.$dname\_day.disabled=true; + document.$formname.$dname\_year.disabled=true; + document.$formname.$dname\_hour.disabled=true; + document.$formname.$dname\_minute.disabled=true; + document.$formname.$dname\_second.disabled=true; + } + + function $dname\_enable() { + document.$formname.$dname\_month.disabled=false; + document.$formname.$dname\_day.disabled=false; + document.$formname.$dname\_year.disabled=false; + document.$formname.$dname\_hour.disabled=false; + document.$formname.$dname\_minute.disabled=false; + document.$formname.$dname\_second.disabled=false; + } + + function $dname\_opencalendar() { + if (! document.$formname.$dname\_month.disabled) { + var calwin=window.open( +"/adm/announcements?pickdate=yes&formname=$formname&element=$dname&month="+ +document.$formname.$dname\_month.value+"&year="+ +document.$formname.$dname\_year.value, + "LONCAPAcal", + "height=350,width=350,scrollbars=yes,resizable=yes,menubar=no"); + } + + } ENDJS - $result .= " \n"; - $result .= " \n"; - $result .= " \n"; $result .= "  "; - $result .= " s\n"; - $result .= "\n"; + if (! $no_hh_mm_ss) { + # Hours + $result .= " \n"; + $result .= " m\n"; + $result .= " s\n"; + } + $result .= "". + &mt('Select Date')."\n\n"; return $result; } ############################################## ############################################## +=pod + =item &get_date_from_form +get_date_from_form retrieves the date specified in an &date_setter form. + Inputs: =over 4 @@ -208,18 +411,26 @@ sub get_date_from_form { if (($tmpsec =~ /^\d+$/) && ($tmpsec >= 0) && ($tmpsec < 60)) { $sec = $tmpsec; } + if (!defined($tmpsec) || $tmpsec eq '') { $sec = 0; } + } else { + $sec = 0; } if (defined($ENV{'form.'.$dname.'_minute'})) { my $tmpmin = $ENV{'form.'.$dname.'_minute'}; if (($tmpmin =~ /^\d+$/) && ($tmpmin >= 0) && ($tmpmin < 60)) { $min = $tmpmin; } + if (!defined($tmpmin) || $tmpmin eq '') { $min = 0; } + } else { + $min = 0; } if (defined($ENV{'form.'.$dname.'_hour'})) { my $tmphour = $ENV{'form.'.$dname.'_hour'}; - if (($tmphour =~ /^\d+$/) && ($tmphour > 0) && ($tmphour < 32)) { + if (($tmphour =~ /^\d+$/) && ($tmphour >= 0) && ($tmphour < 24)) { $hour = $tmphour; } + } else { + $hour = 0; } if (defined($ENV{'form.'.$dname.'_day'})) { my $tmpday = $ENV{'form.'.$dname.'_day'}; @@ -239,7 +450,10 @@ sub get_date_from_form { $year = $tmpyear - 1900; } } - if (eval(&timelocal($sec,$min,$hour,$day,$month,$year))) { + if (($year<70) || ($year>137)) { return undef; } + if (defined($sec) && defined($min) && defined($hour) && + defined($day) && defined($month) && defined($year) && + eval(&timelocal($sec,$min,$hour,$day,$month,$year))) { return &timelocal($sec,$min,$hour,$day,$month,$year); } else { return undef; @@ -249,174 +463,100 @@ sub get_date_from_form { ############################################## ############################################## -sub AscendOrderOptions { - my ($order, $page, $formName)=@_; +=pod - my $OpSel1 = ''; - my $OpSel2 = ''; +=item &pjump_javascript_definition() - if($order eq 'Ascending') { - $OpSel1 = ' selected'; - } else { - $OpSel2 = ' selected'; - } +Returns javascript defining the 'pjump' function, which opens up a +parameter setting wizard. - my $Str = ''; - $Str .= ''."\n"; +=cut +############################################## +############################################## +sub pjump_javascript_definition { + my $Str = <{'orderedSequences'})) { - $Str .= '{$page.'Maps'} eq $data->{$sequence.':title'}) { - $Str .= ' selected'; - $selected = 1; - } - $Str .= '>'.$data->{$sequence.':title'}.''."\n"; - } - $Str .= '{'orderedSequences'})) { - if($data->{$sequence.':title'} eq $map || $map eq 'All Maps') { - foreach my $problem (split(':', $data->{$sequence.':problems'})) { - $Str .= '{$page.'ProblemSelect'} eq - $data->{$problem.':title'}) { - $Str .= ' selected'; - $selected = 1; - } - $Str .= '>'.$data->{$problem.':title'}.''."\n"; - } - } +############################################## +############################################## +sub javascript_nothing { + # mozilla and other browsers work with "''", but IE on mac does not. + my $nothing = "''"; + my $user_browser; + my $user_os; + $user_browser = $ENV{'browser.type'} if (exists($ENV{'browser.type'})); + $user_os = $ENV{'browser.os'} if (exists($ENV{'browser.os'})); + if (! defined($user_browser) || ! defined($user_os)) { + (undef,$user_browser,undef,undef,undef,$user_os) = + &Apache::loncommon::decode_user_agent(); } - $Str .= '{$page.'PartSelect'} eq $part) { - $Str .= ' selected'; - $selected = 1; - } - $Str .= '>'.$part.''."\n"; - } - $Str .= '{$_.':fullname'}; - $Str .= ''."\n"; - } +$formname: The name of the form. If defined the onchange attribute of +the selection box is set to document.$formname.submit(). - $Str .= 'Active'."\n"; - $Str .= 'Expired'."\n"; - $Str .= 'Any'."\n"; + $Str .= ''."\n"; + $Str .= ''."\n"; + $Str .= ''."\n"; $Str .= ''."\n"; } - ######################################################## ######################################################## =pod -=item &MultipleSectionSelect() +=item Progess Window Handling Routines -Inputs: +These routines handle the creation, update, increment, and closure of +progress windows. The progress window reports to the user the number +of items completed and an estimate of the time required to complete the rest. =over 4 -=item $sections A references to an array containing the names of all the -sections used in a class. -=item $selectedSections A reference to an array containing the names of the -currently selected sections. +=item &Create_PrgWin -=back +Writes javascript to the client to open a progress window and returns a +data structure used for bookkeeping. -Returns: a string containing HTML for a multiple select box for -selecting sections of a course. - -The form element name is 'Section'. @$sections is sorted prior to output. - -=cut - -######################################################## -######################################################## -sub MultipleSectionSelect { - my ($sections,$selectedSections)=@_; - - my $Str = ''; - $Str .= ''."\n"; - - return $Str; -} +=over 4 -######################################################## -######################################################## +=item $r Apache request -=pod +=item $title The title of the progress window -=item &Title() +=item $heading A description (usually 1 line) of the process being initiated. -Inputs: $pageName a string containing the name of the page to be sent -to &Apache::loncommon::bodytag. +=item $number_to_do The total number of items being processed. -Returns: string containing being and complete and -as well as a <script> to focus the current window and change its width -and height to 500. Why? I do not know. If you find out, please update -this documentation. +=item $type Either 'popup' or 'inline' (popup is assumed if nothing is + specified) -=cut +=item $width Specify the width in charaters of the input field. -######################################################## -######################################################## -sub Title { - my ($pageName)=@_; +=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 - my $Str = ''; +=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 - $Str .= '<html><head><title>'.$pageName.''."\n"; - $Str .= &Apache::loncommon::bodytag($pageName)."\n"; - $Str .= ''."\n"; +=back - return $Str; -} +Returns a hash containing the progress state data structure. -######################################################## -######################################################## -=pod +=item &Update_PrgWin -=item &CreateHeadings() +Updates the text in the progress indicator. Does not increment the count. +See &Increment_PrgWin. -This function generates the column headings for the chart. +Inputs: =over 4 -Inputs: $CacheData, $keyID, $headings, $spacePadding +=item $r Apache request -$CacheData: pointer to a hash tied to the cached data database +=item $prog_state Pointer to the data structure returned by &Create_PrgWin -$keyID: a pointer to an array containing the names of the data -held in a column and is used as part of a key into $CacheData +=item $displaystring The string to write to the status indicator -$headings: The names of the headings for the student information +=back -$spacePadding: The spaces to go between columns +Returns: none -Output: $Str -$Str: A formatted string of the table column headings. +=item Increment_PrgWin -=back +Increment the count of items completed for the progress window by 1. -=cut +Inputs: -######################################################## -######################################################## -sub CreateHeadings { - my ($data,$keyID,$headings,$displayString,$format)=@_; - my $Str=''; - my $formatting = ''; - - for(my $index=0; $index<(scalar @$headings); $index++) { - my $currentHeading=$headings->[$index]; - if($format eq 'preformatted') { - my @dataLength=split(//,$currentHeading); - my $length=scalar @dataLength; - $formatting = (' 'x - ($data->{$keyID->[$index].':columnWidth'}-$length)); - } - my $linkdata=$keyID->[$index]; - - my $tempString = $displayString; - $tempString =~ s/LINKDATA/$linkdata/; - $tempString =~ s/DISPLAYDATA/$currentHeading/; - $tempString =~ s/FORMATTING/$formatting/; +=over 4 - $Str .= $tempString; - } +=item $r Apache request - return $Str; -} +=item $prog_state Pointer to the data structure returned by Create_PrgWin -######################################################## -######################################################## +=item $extraInfo A description of the items being iterated over. Typically +'student'. -=pod +=back -=item &FormatStudentInformation() +Returns: none -This function produces a formatted string of the student\'s information: -username, domain, section, full name, and PID. -=over 4 +=item Close_PrgWin -Input: $cache, $name, $keyID, $spacePadding +Closes the progress window. -$cache: This is a pointer to a hash that is tied to the cached data - -$name: The name and domain of the current student in name:domain format +Inputs: -$keyID: A pointer to an array holding the names used to +=over 4 -remove data from the hash. They represent the name of the data to be removed. +=item $r Apache request -$spacePadding: Extra spaces that represent the space between columns +=item $prog_state Pointer to the data structure returned by Create_PrgWin -Output: $Str +=back -$Str: Formatted string. +Returns: none =back @@ -611,87 +692,369 @@ $Str: Formatted string. ######################################################## ######################################################## -sub FormatStudentInformation { - my ($data,$name,$keyID,$displayString,$format)=@_; - my $Str=''; - my $currentColumn; - - for(my $index=0; $index<(scalar @$keyID); $index++) { - $currentColumn=$data->{$name.':'.$keyID->[$index]}; - - if($format eq 'preformatted') { - my @dataLength=split(//,$currentColumn); - my $length=scalar @dataLength; - $currentColumn.= (' 'x - ($data->{$keyID->[$index].':columnWidth'}-$length)); - } - - my $tempString = $displayString; - $tempString =~ s/DISPLAYDATA/$currentColumn/; - - $Str .= $tempString; - } - return $Str; +my $uniq=0; +sub get_uniq_name { + $uniq++; + return 'uniquename'.$uniq; } -######################################################## -######################################################## - # Create progress sub Create_PrgWin { - my ($r, $title, $heading, $number_to_do)=@_; - $r->print('"); - - my %prog_state; - $prog_state{'now'}=0; - $prog_state{'since'}=time; - $prog_state{'started'}=time; - $prog_state{'total'}=$number_to_do; + "popwin.document.close();}". + "\nwindow.setTimeout(openpopwin,0)"); + $prog_state{'formname'}='popremain'; + $prog_state{'inputname'}="remaining"; + } elsif ($type eq 'inline') { + $prog_state{'window'}='window'; + if (!$formname) { + $prog_state{'formname'}=&get_uniq_name(); + &r_print($r,'
'); + } else { + $prog_state{'formname'}=$formname; + } + if (!$inputname) { + $prog_state{'inputname'}=&get_uniq_name(); + &r_print($r,$heading.' '); + } else { + $prog_state{'inputname'}=$inputname; + + } + if (!$formname) { &r_print($r,'
'); } + &Update_PrgWin($r,\%prog_state,&mt('Starting')); + } - $r->rflush(); + $prog_state{'done'}=0; + $prog_state{'firststart'}=&Time::HiRes::time(); + $prog_state{'laststart'}=&Time::HiRes::time(); + $prog_state{'max'}=$number_to_do; + return %prog_state; } # update progress sub Update_PrgWin { my ($r,$prog_state,$displayString)=@_; - $r->print(''); - $$prog_state{'started'}=time; - $r->rflush(); + &r_print($r,''); + $$prog_state{'laststart'}=&Time::HiRes::time(); } # increment progress state sub Increment_PrgWin { my ($r,$prog_state,$extraInfo)=@_; - $$prog_state{'now'}++; - $r->print(''); - $$prog_state{'started'}=time; - $r->rflush(); + $$prog_state{'done'}++; + my $time_est= (&Time::HiRes::time() - $$prog_state{'firststart'})/ + $$prog_state{'done'} * + ($$prog_state{'max'}-$$prog_state{'done'}); + $time_est = int($time_est); + if (int ($time_est/60) > 0) { + my $min = int($time_est/60); + my $sec = $time_est % 60; + $time_est = $min.' '.&mt('minutes'); + if ($min < 10) { + if ($sec > 1) { + $time_est.= ', '.$sec.' '.&mt('seconds'); + } elsif ($sec > 0) { + $time_est.= ', '.$sec.' '.&mt('second'); + } + } + } else { + $time_est .= ' '.&mt('seconds'); + } + my $lasttime = &Time::HiRes::time()-$$prog_state{'laststart'}; + if ($lasttime > 9) { + $lasttime = int($lasttime); + } elsif ($lasttime < 0.01) { + $lasttime = 0; + } else { + $lasttime = sprintf("%3.2f",$lasttime); + } + if ($lasttime == 1) { + $lasttime = '('.$lasttime.' '.&mt('second for').' '.$extraInfo.')'; + } else { + $lasttime = '('.$lasttime.' '.&mt('seconds for').' '.$extraInfo.')'; + } + # + my $user_browser = $ENV{'browser.type'} if (exists($ENV{'browser.type'})); + my $user_os = $ENV{'browser.os'} if (exists($ENV{'browser.os'})); + if (! defined($user_browser) || ! defined($user_os)) { + (undef,$user_browser,undef,undef,undef,$user_os) = + &Apache::loncommon::decode_user_agent(); + } + if ($user_browser eq 'explorer' && $user_os =~ 'mac') { + $lasttime = ''; + } + &r_print($r,''); + $$prog_state{'laststart'}=&Time::HiRes::time(); } # close Progress Line sub Close_PrgWin { my ($r,$prog_state)=@_; - $r->print(''."\n"); + if ($$prog_state{'type'} eq 'popup') { + &r_print($r,''."\n"); + } elsif ($$prog_state{'type'} eq 'inline') { + &Update_PrgWin($r,$prog_state,&mt('Done')); + } undef(%$prog_state); - $r->rflush(); } +sub r_print { + my ($r,$to_print)=@_; + if ($r) { + $r->print($to_print); + $r->rflush(); + } else { + print($to_print); + } +} + +# ------------------------------------------------------- Puts directory header + +sub crumbs { + my ($uri,$target,$prefix,$form,$size)=@_; + if (! defined($size)) { + $size = '+2'; + } + my $output='
'.$prefix.'/'; + if ($ENV{'user.adv'}) { + my $path=$prefix.'/'; + foreach (split('/',$uri)) { + unless ($_) { next; } + $path.=$_; + unless ($path eq $uri) { $path.='/'; } + my $linkpath=$path; + if ($form) { + $linkpath="javascript:$form.action='$path';$form.submit();"; + } + $output.=''.$_.'/'; + } + } else { + $output.=$uri; + } + unless ($uri=~/\/$/) { $output=~s/\/$//; } + return $output.'
'; +} + +# ------------------------------------------------- Output headers for HTMLArea + +sub htmlareaheaders { + unless (&htmlareablocked()) { return ''; } + my $lang='en'; + return (< + _editor_url="/htmlarea/"; + + + + + +ENDHEADERS +} + +# ---------------------------------------------------------- Script to activate + +sub htmlareaactive { + unless (&htmlareablocked()) { return ''; } + return (< + HTMLArea.replaceAll(); + +ENDSCRIPT +} + +# --------------------------------------------------------------------- Blocked + +sub htmlareablocked { + unless (&htmlareabrowser()) { return ''; } + return 1; +} + +# ---------------------------------------- Browser capable of running HTMLArea? + +sub htmlareabrowser { + return 1; +} + +############################################################ +############################################################ + +=pod + +=item breadcrumbs + +Compiles the previously registered breadcrumbs into an series of links. +FAQ and BUG links will be placed on the left side of the table if they +are defined for the last registered breadcrumb. +Additionally supports a 'component', which will be displayed on the +right side of the table (without a link). +A link to help for the component will be included if one is specified. + +All inputs can be undef without problems. + +Inputs: $color (the background color of the table returned), + $component (the large text on the right side of the table), + $component_help + $function (role to get colors from) + $domain (domian of role) + $menulink (boolean, controls whether to include a link to /adm/menu) + +Returns a string containing breadcrumbs for the current page. + +=item clear_breadcrumbs + +Clears the previously stored breadcrumbs. + +=item add_breadcrumb + +Pushes a breadcrumb on the stack of crumbs. + +input: $breadcrumb, a hash reference. The keys 'href','title', and 'text' +are required. If present the keys 'faq' and 'bug' will be used to provide +links to the FAQ and bug sites. + +returns: nothing + +=cut + +############################################################ +############################################################ +{ + my @Crumbs; + + sub breadcrumbs { + my ($color,$component,$component_help,$function,$domain,$menulink) = + @_; + if (! defined($color)) { + if (! defined($function)) { + $function = &Apache::loncommon::get_users_function(); + } + $color = &Apache::loncommon::designparm($function.'.tabbg', + $domain); + } + # + my $Str = "\n". + ''. + ''; + # + if (defined($component)) { + $Str .= ''; + } + $Str .= '
'. + ''; + # + # Make the faq and bug data cascade + my $faq = ''; + my $bug = ''; + # The last breadcrumb does not have a link, so handle it separately. + my $last = pop(@Crumbs); + # + # The first one should be the course or a menu link + if (!defined($menulink)) { $menulink=1; } + if ($menulink) { + my $description = 'Menu'; + if (exists($ENV{'request.course.id'}) && + $ENV{'request.course.id'} ne '') { + $description = + $ENV{'course.'.$ENV{'request.course.id'}.'.description'}; + } + unshift(@Crumbs,{ + href =>'/adm/menu', + title =>'Go to main menu', + target =>'_top', + text =>$description, + }); + } + my $links .= + join('->', + map { + $faq = $_->{'faq'} if (exists($_->{'faq'})); + $bug = $_->{'bug'} if (exists($_->{'bug'})); + my $result = '{'target'}) && $_->{'target'} ne '') { + $result .= 'target="'.$_->{'target'}.'" '; + } + $result .='title="'.&mt($_->{'title'}).'">'. + &mt($_->{'text'}).''; + $result; + } @Crumbs + ); + $links .= '->' if ($links ne ''); + $links .= ''.$last->{'text'}.''; + # + my $icons = ''; + $faq = $last->{'faq'} if (exists($last->{'faq'})); + $bug = $last->{'bug'} if (exists($last->{'bug'})); + if ($faq ne '') { + $icons .= &Apache::loncommon::help_open_faq($faq); + } + if ($bug ne '') { + $icons .= &Apache::loncommon::help_open_bug($bug); + } + if ($icons ne '') { + $Str .= $icons.' '; + } + # + $Str .= $links.''. + ''.&mt($component).''; + if (defined($component_help)) { + $Str .= + &Apache::loncommon::help_open_topic($component_help); + } + $Str.= '
'."\n"; + # + # Return the @Crumbs stack to what we started with + push(@Crumbs,$last); + shift(@Crumbs); + # + return $Str; + } + + sub clear_breadcrumbs { + undef(@Crumbs); + } + + sub add_breadcrumb { + push (@Crumbs,@_); + } + +} # End of scope for @Crumbs + +############################################################ +############################################################ + + 1; + __END__ 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.