Annotation of loncom/interface/lonhtmlcommon.pm, revision 1.22
1.2 www 1: # The LearningOnline Network with CAPA
2: # a pile of common html routines
3: #
1.22 ! matthew 4: # $Id: lonhtmlcommon.pm,v 1.21 2003/05/12 22:04:41 matthew 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.10 matthew 58: use Time::Local;
1.1 stredwic 59: use strict;
60:
1.10 matthew 61: ##############################################
62: ##############################################
63:
64: =pod
65:
66: =item &date_setter
67:
1.22 ! matthew 68: &date_setter returns html and javascript for a compact date-setting form.
! 69: To retrieve values from it, use &get_date_from_form().
! 70:
1.10 matthew 71: Inputs
72:
73: =over 4
74:
75: =item $dname
76:
77: The name to prepend to the form elements.
78: The form elements defined will be dname_year, dname_month, dname_day,
79: dname_hour, dname_min, and dname_sec.
80:
81: =item $currentvalue
82:
83: The current setting for this time parameter. A unix format time
84: (time in seconds since the beginning of Jan 1st, 1970, GMT.
85: An undefined value is taken to indicate the value is the current time.
86: Also, to be explicit, a value of 'now' also indicates the current time.
87:
1.22 ! matthew 88: =back
! 89:
! 90: Bugs
! 91:
! 92: The method used to restrict user input will fail in the year 2400.
! 93:
1.10 matthew 94: =cut
95:
96: ##############################################
97: ##############################################
98: sub date_setter {
99: my ($formname,$dname,$currentvalue) = @_;
100: if (! defined($currentvalue) || $currentvalue eq 'now') {
101: $currentvalue = time;
102: }
103: # other potentially useful values: wkday,yrday,is_daylight_savings
104: my ($sec,$min,$hour,$mday,$month,$year,undef,undef,undef) =
105: localtime($currentvalue);
106: $year += 1900;
107: my $result = "\n<!-- $dname date setting form -->\n";
108: $result .= <<ENDJS;
109: <script language="Javascript">
110: function $dname\_checkday() {
111: var day = document.$formname.$dname\_day.value;
112: var month = document.$formname.$dname\_month.value;
113: var year = document.$formname.$dname\_year.value;
114: var valid = true;
115: if (day < 1) {
116: document.$formname.$dname\_day.value = 1;
117: }
118: if (day > 31) {
119: document.$formname.$dname\_day.value = 31;
120: }
121: if ((month == 1) || (month == 3) || (month == 5) ||
122: (month == 7) || (month == 8) || (month == 10) ||
123: (month == 12)) {
124: if (day > 31) {
125: document.$formname.$dname\_day.value = 31;
126: day = 31;
127: }
128: } else if (month == 2 ) {
129: if ((year % 4 == 0) && (year % 100 != 0)) {
130: if (day > 29) {
131: document.$formname.$dname\_day.value = 29;
132: }
133: } else if (day > 29) {
134: document.$formname.$dname\_day.value = 28;
135: }
136: } else if (day > 30) {
137: document.$formname.$dname\_day.value = 30;
138: }
139: }
140: </script>
141: ENDJS
142: $result .= " <select name=\"$dname\_month\" ".
143: "onChange=\"javascript:$dname\_checkday()\" >\n";
144: my @Months = qw/January February March April May June
145: July August September October November December/;
146: # Pad @Months with a bogus value to make indexing easier
147: unshift(@Months,'If you can read this an error occurred');
148: for(my $m = 1;$m <=$#Months;$m++) {
149: $result .= " <option value=\"$m\" ";
150: $result .= "selected " if ($m-1 == $month);
151: $result .= "> $Months[$m] </option>\n";
152: }
153: $result .= " </select>\n";
154: $result .= " <input type=\"text\" name=\"$dname\_day\" ".
155: "value=\"$mday\" size=\"3\" ".
156: "onChange=\"javascript:$dname\_checkday()\" />\n";
157: $result .= " <input type=\"year\" name=\"$dname\_year\" ".
158: "value=\"$year\" size=\"5\" ".
159: "onChange=\"javascript:$dname\_checkday()\" />\n";
160: $result .= " ";
161: $result .= " <select name=\"$dname\_hour\" >\n";
162: for (my $h = 0;$h<24;$h++) {
163: $result .= " <option value=\"$h\" ";
164: $result .= "selected " if ($hour == $h);
165: $result .= "> ";
166: if ($h == 0) {
167: $result .= "12 am";
168: } elsif($h == 12) {
169: $result .= "12 noon";
170: } elsif($h < 12) {
171: $result .= "$h am";
172: } else {
173: $result .= $h-12 ." pm";
174: }
175: $result .= " </option>\n";
176: }
177: $result .= " </select>\n";
178: $result .= " <input type=\"text\" name=\"$dname\_minute\" ".
179: "value=\"$min\" size=\"3\" /> m\n";
180: $result .= " <input type=\"text\" name=\"$dname\_second\" ".
181: "value=\"$sec\" size=\"3\" /> s\n";
182: $result .= "<!-- end $dname date setting form -->\n";
183: return $result;
184: }
185:
186: ##############################################
187: ##############################################
188:
1.22 ! matthew 189: =pod
! 190:
1.10 matthew 191: =item &get_date_from_form
1.22 ! matthew 192:
! 193: get_date_from_form retrieves the date specified in an &date_setter form.
1.10 matthew 194:
195: Inputs:
196:
197: =over 4
198:
199: =item $dname
200:
201: The name passed to &datesetter, which prefixes the form elements.
202:
203: =item $defaulttime
204:
205: The unix time to use as the default in case of poor inputs.
206:
207: =back
208:
209: Returns: Unix time represented in the form.
210:
211: =cut
212:
213: ##############################################
214: ##############################################
215: sub get_date_from_form {
216: my ($dname) = @_;
217: my ($sec,$min,$hour,$day,$month,$year);
218: #
219: if (defined($ENV{'form.'.$dname.'_second'})) {
220: my $tmpsec = $ENV{'form.'.$dname.'_second'};
221: if (($tmpsec =~ /^\d+$/) && ($tmpsec >= 0) && ($tmpsec < 60)) {
222: $sec = $tmpsec;
223: }
224: }
225: if (defined($ENV{'form.'.$dname.'_minute'})) {
226: my $tmpmin = $ENV{'form.'.$dname.'_minute'};
227: if (($tmpmin =~ /^\d+$/) && ($tmpmin >= 0) && ($tmpmin < 60)) {
228: $min = $tmpmin;
229: }
230: }
231: if (defined($ENV{'form.'.$dname.'_hour'})) {
232: my $tmphour = $ENV{'form.'.$dname.'_hour'};
233: if (($tmphour =~ /^\d+$/) && ($tmphour > 0) && ($tmphour < 32)) {
234: $hour = $tmphour;
235: }
236: }
237: if (defined($ENV{'form.'.$dname.'_day'})) {
238: my $tmpday = $ENV{'form.'.$dname.'_day'};
239: if (($tmpday =~ /^\d+$/) && ($tmpday > 0) && ($tmpday < 32)) {
240: $day = $tmpday;
241: }
242: }
243: if (defined($ENV{'form.'.$dname.'_month'})) {
244: my $tmpmonth = $ENV{'form.'.$dname.'_month'};
245: if (($tmpmonth =~ /^\d+$/) && ($tmpmonth > 0) && ($tmpmonth < 13)) {
246: $month = $tmpmonth - 1;
247: }
248: }
249: if (defined($ENV{'form.'.$dname.'_year'})) {
250: my $tmpyear = $ENV{'form.'.$dname.'_year'};
251: if (($tmpyear =~ /^\d+$/) && ($tmpyear > 1900)) {
252: $year = $tmpyear - 1900;
253: }
254: }
255: if (eval(&timelocal($sec,$min,$hour,$day,$month,$year))) {
256: return &timelocal($sec,$min,$hour,$day,$month,$year);
257: } else {
258: return undef;
259: }
1.20 matthew 260: }
261:
262: ##############################################
263: ##############################################
264:
265: =pod
266:
267: =item &pjump_javascript_definition()
268:
269: Returns javascript defining the 'pjump' function, which opens up a
270: parameter setting wizard.
271:
272: =cut
273:
274: ##############################################
275: ##############################################
276: sub pjump_javascript_definition {
277: my $Str = <<END;
278: function pjump(type,dis,value,marker,ret,call) {
279: parmwin=window.open("/adm/rat/parameter.html?type="+escape(type)
280: +"&value="+escape(value)+"&marker="+escape(marker)
281: +"&return="+escape(ret)
282: +"&call="+escape(call)+"&name="+escape(dis),"LONCAPAparms",
283: "height=350,width=350,scrollbars=no,menubar=no");
284: }
285: END
286: return $Str;
1.10 matthew 287: }
288:
289: ##############################################
290: ##############################################
1.17 matthew 291:
292: =pod
293:
294: =item &javascript_nothing()
295:
296: Return an appropriate null for the users browser. This is used
297: as the first arguement for window.open calls when you want a blank
298: window that you can then write to.
299:
300: =cut
301:
302: ##############################################
303: ##############################################
304: sub javascript_nothing {
305: # mozilla and other browsers work with "''", but IE on mac does not.
306: my $nothing = "''";
307: my $user_browser;
308: my $user_os;
309: $user_browser = $ENV{'browser.type'} if (exists($ENV{'browser.type'}));
310: $user_os = $ENV{'browser.os'} if (exists($ENV{'browser.os'}));
311: if (! defined($user_browser) || ! defined($user_os)) {
312: (undef,$user_browser,undef,undef,undef,$user_os) =
313: &Apache::loncommon::decode_user_agent();
314: }
315: if ($user_browser eq 'explorer' && $user_os =~ 'mac') {
316: $nothing = "'javascript:void(0);'";
317: }
318: return $nothing;
319: }
320:
1.21 matthew 321:
1.17 matthew 322: ##############################################
323: ##############################################
324:
1.21 matthew 325: =pod
1.17 matthew 326:
1.21 matthew 327: =item &StatusOptions()
1.10 matthew 328:
1.21 matthew 329: Returns html for a selection box which allows the user to choose the
330: enrollment status of students. The selection box name is 'Status'.
1.6 stredwic 331:
1.21 matthew 332: Inputs:
1.6 stredwic 333:
1.21 matthew 334: $status: the currently selected status. If undefined the value of
335: $ENV{'form.Status'} is taken. If that is undefined, a value of 'Active'
336: is used.
1.6 stredwic 337:
1.21 matthew 338: $formname: The name of the form. If defined the onchange attribute of
339: the selection box is set to document.$formname.submit().
1.6 stredwic 340:
1.21 matthew 341: $size: the size (number of lines) of the selection box.
1.6 stredwic 342:
1.21 matthew 343: Returns: a perl string as described.
1.1 stredwic 344:
1.21 matthew 345: =cut
1.9 stredwic 346:
1.21 matthew 347: ##############################################
348: ##############################################
349: sub StatusOptions {
350: my ($status, $formName,$size)=@_;
351: $size = 1 if (!defined($size));
352: if (! defined($status)) {
353: $status = 'Active';
354: $status = $ENV{'form.Status'} if (exists($ENV{'form.Status'}));
1.9 stredwic 355: }
1.1 stredwic 356:
357: my $OpSel1 = '';
358: my $OpSel2 = '';
359: my $OpSel3 = '';
360:
361: if($status eq 'Any') { $OpSel3 = ' selected'; }
362: elsif($status eq 'Expired' ) { $OpSel2 = ' selected'; }
363: else { $OpSel1 = ' selected'; }
364:
365: my $Str = '';
366: $Str .= '<select name="Status"';
367: if(defined($formName) && $formName ne '') {
368: $Str .= ' onchange="document.'.$formName.'.submit()"';
369: }
1.21 matthew 370: $Str .= ' size="'.$size.'" ';
1.1 stredwic 371: $Str .= '>'."\n";
1.21 matthew 372: $Str .= '<option value="Active" '.$OpSel1.'>'.
373: 'Currently Enrolled</option>'."\n";
374: $Str .= '<option value="Expired" '.$OpSel2.'>'.
375: 'Previously Enrolled</option>'."\n";
376: $Str .= '<option value="Any" '.$OpSel3.'>'.
377: 'Any Enrollment Status</option>'."\n";
1.1 stredwic 378: $Str .= '</select>'."\n";
379: }
380:
1.12 matthew 381:
382: ########################################################
383: ########################################################
384:
385: =pod
386:
387: =item &MultipleSectionSelect()
388:
389: Inputs:
390:
391: =over 4
392:
393: =item $sections A references to an array containing the names of all the
394: sections used in a class.
395:
396: =item $selectedSections A reference to an array containing the names of the
397: currently selected sections.
398:
399: =back
400:
401: Returns: a string containing HTML for a multiple select box for
402: selecting sections of a course.
403:
404: The form element name is 'Section'. @$sections is sorted prior to output.
405:
406: =cut
407:
408: ########################################################
409: ########################################################
1.5 stredwic 410: sub MultipleSectionSelect {
411: my ($sections,$selectedSections)=@_;
412:
413: my $Str = '';
1.7 stredwic 414: $Str .= '<select name="Section" multiple="true" size="4">'."\n";
1.5 stredwic 415:
1.11 minaeibi 416: foreach (sort @$sections) {
1.5 stredwic 417: $Str .= '<option';
418: foreach my $selected (@$selectedSections) {
419: if($_ eq $selected) {
420: $Str .= ' selected=""';
421: }
422: }
423: $Str .= '>'.$_.'</option>'."\n";
424: }
425: $Str .= '</select>'."\n";
1.12 matthew 426:
1.5 stredwic 427: return $Str;
428: }
429:
1.12 matthew 430: ########################################################
431: ########################################################
432:
433: =pod
434:
435: =item &Title()
436:
437: Inputs: $pageName a string containing the name of the page to be sent
438: to &Apache::loncommon::bodytag.
439:
440: Returns: string containing being <html> and complete <head> and <title>
441: as well as a <script> to focus the current window and change its width
442: and height to 500. Why? I do not know. If you find out, please update
443: this documentation.
444:
445: =cut
446:
447: ########################################################
448: ########################################################
1.1 stredwic 449: sub Title {
450: my ($pageName)=@_;
451:
452: my $Str = '';
453:
454: $Str .= '<html><head><title>'.$pageName.'</title></head>'."\n";
1.8 www 455: $Str .= &Apache::loncommon::bodytag($pageName)."\n";
1.1 stredwic 456: $Str .= '<script>window.focus(); window.width=500;window.height=500;';
457: $Str .= '</script>'."\n";
458:
459: return $Str;
460: }
461:
1.12 matthew 462: ########################################################
463: ########################################################
464:
1.1 stredwic 465: =pod
466:
1.13 matthew 467: =item &CreateHeadings()
1.1 stredwic 468:
469: This function generates the column headings for the chart.
470:
471: =over 4
472:
1.4 stredwic 473: Inputs: $CacheData, $keyID, $headings, $spacePadding
1.1 stredwic 474:
475: $CacheData: pointer to a hash tied to the cached data database
476:
1.4 stredwic 477: $keyID: a pointer to an array containing the names of the data
1.1 stredwic 478: held in a column and is used as part of a key into $CacheData
479:
480: $headings: The names of the headings for the student information
481:
482: $spacePadding: The spaces to go between columns
483:
484: Output: $Str
485:
486: $Str: A formatted string of the table column headings.
487:
488: =back
489:
490: =cut
491:
1.12 matthew 492: ########################################################
493: ########################################################
1.4 stredwic 494: sub CreateHeadings {
495: my ($data,$keyID,$headings,$displayString,$format)=@_;
1.1 stredwic 496: my $Str='';
1.4 stredwic 497: my $formatting = '';
1.1 stredwic 498:
499: for(my $index=0; $index<(scalar @$headings); $index++) {
1.4 stredwic 500: my $currentHeading=$headings->[$index];
501: if($format eq 'preformatted') {
502: my @dataLength=split(//,$currentHeading);
503: my $length=scalar @dataLength;
504: $formatting = (' 'x
505: ($data->{$keyID->[$index].':columnWidth'}-$length));
506: }
507: my $linkdata=$keyID->[$index];
508:
1.1 stredwic 509: my $tempString = $displayString;
510: $tempString =~ s/LINKDATA/$linkdata/;
1.4 stredwic 511: $tempString =~ s/DISPLAYDATA/$currentHeading/;
512: $tempString =~ s/FORMATTING/$formatting/;
513:
1.1 stredwic 514: $Str .= $tempString;
515: }
516:
517: return $Str;
518: }
519:
1.12 matthew 520: ########################################################
521: ########################################################
522:
1.1 stredwic 523: =pod
524:
525: =item &FormatStudentInformation()
526:
1.10 matthew 527: This function produces a formatted string of the student\'s information:
1.1 stredwic 528: username, domain, section, full name, and PID.
529:
530: =over 4
531:
1.4 stredwic 532: Input: $cache, $name, $keyID, $spacePadding
1.1 stredwic 533:
534: $cache: This is a pointer to a hash that is tied to the cached data
535:
536: $name: The name and domain of the current student in name:domain format
537:
1.4 stredwic 538: $keyID: A pointer to an array holding the names used to
1.1 stredwic 539:
540: remove data from the hash. They represent the name of the data to be removed.
541:
542: $spacePadding: Extra spaces that represent the space between columns
543:
544: Output: $Str
545:
546: $Str: Formatted string.
547:
548: =back
549:
550: =cut
551:
1.12 matthew 552: ########################################################
553: ########################################################
1.1 stredwic 554: sub FormatStudentInformation {
1.4 stredwic 555: my ($data,$name,$keyID,$displayString,$format)=@_;
1.1 stredwic 556: my $Str='';
1.4 stredwic 557: my $currentColumn;
558:
559: for(my $index=0; $index<(scalar @$keyID); $index++) {
560: $currentColumn=$data->{$name.':'.$keyID->[$index]};
1.1 stredwic 561:
1.4 stredwic 562: if($format eq 'preformatted') {
563: my @dataLength=split(//,$currentColumn);
564: my $length=scalar @dataLength;
565: $currentColumn.= (' 'x
566: ($data->{$keyID->[$index].':columnWidth'}-$length));
1.1 stredwic 567: }
568:
1.4 stredwic 569: my $tempString = $displayString;
570: $tempString =~ s/DISPLAYDATA/$currentColumn/;
571:
572: $Str .= $tempString;
1.1 stredwic 573: }
574:
575: return $Str;
1.7 stredwic 576: }
1.12 matthew 577:
578: ########################################################
579: ########################################################
1.7 stredwic 580:
581: # Create progress
582: sub Create_PrgWin {
1.14 albertel 583: my ($r, $title, $heading, $number_to_do)=@_;
1.7 stredwic 584: $r->print('<script>'.
585: "popwin=open(\'\',\'popwin\',\'width=400,height=100\');".
1.14 albertel 586: "popwin.document.writeln(\'<html><head><title>$title</title></head>".
587: "<body bgcolor=\"#88DDFF\">".
1.7 stredwic 588: "<h4>$heading</h4>".
589: "<form name=popremain>".
1.14 albertel 590: "<input type=text size=55 name=remaining value=Starting></form>".
1.7 stredwic 591: "</body></html>\');".
592: "popwin.document.close();".
593: "</script>");
594:
1.14 albertel 595: my %prog_state;
1.16 albertel 596: $prog_state{'done'}=0;
597: $prog_state{'firststart'}=time;
598: $prog_state{'laststart'}=time;
599: $prog_state{'max'}=$number_to_do;
1.14 albertel 600:
1.7 stredwic 601: $r->rflush();
1.14 albertel 602: return %prog_state;
1.7 stredwic 603: }
604:
605: # update progress
606: sub Update_PrgWin {
1.14 albertel 607: my ($r,$prog_state,$displayString)=@_;
1.7 stredwic 608: $r->print('<script>popwin.document.popremain.remaining.value="'.
609: $displayString.'";</script>');
1.16 albertel 610: $$prog_state{'laststart'}=time;
1.14 albertel 611: $r->rflush();
612: }
613:
614: # increment progress state
615: sub Increment_PrgWin {
616: my ($r,$prog_state,$extraInfo)=@_;
1.16 albertel 617: $$prog_state{'done'}++;
618: my $time_est= (time - $$prog_state{'firststart'})/$$prog_state{'done'} *
619: ($$prog_state{'max'}-$$prog_state{'done'});
620: $time_est = int($time_est);
621: if (int ($time_est/60) > 0) {
622: my $min = int($time_est/60);
623: my $sec = $time_est % 60;
624: $time_est = $min.' minutes';
625: if ($sec > 1) {
626: $time_est.= ', '.$sec.' seconds';
627: } elsif ($sec > 0) {
628: $time_est.= ', '.$sec.' second';
629: }
630: } else {
631: $time_est .= ' seconds';
632: }
1.19 matthew 633: my $lasttime = time-$$prog_state{'laststart'};
634: if ($lasttime == 1) {
635: $lasttime = '('.$lasttime.' second for '.$extraInfo.')';
636: } else {
637: $lasttime = '('.$lasttime.' seconds for '.$extraInfo.')';
638: }
1.14 albertel 639: $r->print('<script>popwin.document.popremain.remaining.value="'.
1.16 albertel 640: $$prog_state{'done'}.'/'.$$prog_state{'max'}.
1.19 matthew 641: ': '.$time_est.' remaining '.$lasttime.'";'.'</script>');
1.16 albertel 642: $$prog_state{'laststart'}=time;
1.7 stredwic 643: $r->rflush();
644: }
645:
646: # close Progress Line
647: sub Close_PrgWin {
1.14 albertel 648: my ($r,$prog_state)=@_;
1.7 stredwic 649: $r->print('<script>popwin.close()</script>'."\n");
1.14 albertel 650: undef(%$prog_state);
1.7 stredwic 651: $r->rflush();
1.1 stredwic 652: }
653:
654: 1;
655: __END__
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>