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