';
+ }
+ return $return;
+}
-=pod
+# display_usage
+#
+# Generates a div containing a block, filled to show percentage of current quota used
+#
+# Quotas available for user portfolios, group portfolios, authoring spaces, and course
+# content stored directly within a course (i.e., excluding published content).
+#
-=item &MultipleSectionSelect()
+sub display_usage {
+ my ($current_disk_usage,$disk_quota,$context) = @_;
+ my $usage = $current_disk_usage/1024;
+ my $quota = $disk_quota/1024;
+ my $percent;
+ if ($disk_quota == 0) {
+ $percent = 100.0;
+ } else {
+ $percent = 100*($current_disk_usage/$disk_quota);
+ }
+ $usage = sprintf("%.2f",$usage);
+ $quota = sprintf("%.2f",$quota);
+ $percent = sprintf("%.0f",$percent);
+ my ($color,$cssclass);
+ if ($percent <= 60) {
+ $color = '#00A000';
+ } elsif ($percent > 60 && $percent < 90) {
+ $color = '#FFD300';
+ $cssclass = 'class="LC_warning"';
+ } elsif( $percent >= 90) {
+ $color = '#FF0000';
+ $cssclass = 'class="LC_error"';
+ }
+ my $prog_width = $percent;
+ if ($prog_width > 100) {
+ $prog_width = 100;
+ }
+ my $display = 'block';
+ if ($context eq 'authoring') {
+ $display = 'inline';
+ }
+ return '
+
'.&mt('Currently using [_1] of the [_2] available.',$usage.' MB ('.$percent.'%)',$quota.' MB')."\n".
+'
'."\n".
+' '."\n".
+'
'."\n".
+'
';
+}
-Inputs:
+##############################################
+##############################################
-=over 4
+# topic_bar
+#
+# Generates a div containing an (optional) number with a white background followed by a
+# title with a background color defined in the corresponding CSS: LC_topic_bar
+# Inputs:
+# 1. number to display.
+# If input for number is empty only the title will be displayed.
+# 2. title text to display.
+# 3. optional id for the
+# Outputs - a scalar containing html mark-up for the div.
+
+sub topic_bar {
+ my ($num,$title,$id) = @_;
+ my $number = '';
+ if ($num ne '') {
+ $number = ''.$num.'';
+ }
+ if ($id ne '') {
+ $id = 'id="'.$id.'"';
+ }
+ return '
'.$number.$title.'
';
+}
-=item $sections A references to an array containing the names of all the
-sections used in a class.
+##############################################
+##############################################
+# echo_form_input
+#
+# Generates html markup to add form elements from the referrer page
+# as hidden form elements (values encoded) in the new page.
+#
+# Intended to support two types of use
+# (a) to allow backing up to earlier pages in a multi-page
+# form submission process using a breadcrumb trail.
+#
+# (b) to allow the current page to be reloaded with form elements
+# set on previous page to remain unchanged. An example would
+# be where the a page containing a dynamically-built table of data is
+# is to be redisplayed, with only the sort order of the data changed.
+#
+# Inputs:
+# 1. Reference to array of form elements in the submitted form on
+# the referrer page which are to be excluded from the echoed elements.
+#
+# 2. Reference to array of regular expressions, which if matched in the
+# name of the form element n the referrer page will be omitted from echo.
+#
+# Outputs: A scalar containing the html markup for the echoed form
+# elements (all as hidden elements, with values encoded).
-=item $selectedSections A reference to an array containing the names of the
-currently selected sections.
-=back
+sub echo_form_input {
+ my ($excluded,$regexps) = @_;
+ my $output = '';
+ foreach my $key (keys(%env)) {
+ if ($key =~ /^form\.(.+)$/) {
+ my $name = $1;
+ my $match = 0;
+ if (ref($excluded) eq 'ARRAY') {
+ next if (grep(/^\Q$name\E$/,@{$excluded}));
+ }
+ if (ref($regexps) eq 'ARRAY') {
+ if (@{$regexps} > 0) {
+ foreach my $regexp (@{$regexps}) {
+ if ($name =~ /$regexp/) {
+ $match = 1;
+ last;
+ }
+ }
+ }
+ }
+ next if ($match);
+ if (ref($env{$key}) eq 'ARRAY') {
+ foreach my $value (@{$env{$key}}) {
+ $value = &HTML::Entities::encode($value,'<>&"');
+ $output .= ''."\n";
+ }
+ } else {
+ my $value = &HTML::Entities::encode($env{$key},'<>&"');
+ $output .= ''."\n";
+ }
+ }
+ }
+ return $output;
+}
-Returns: a string containing HTML for a multiple select box for
-selecting sections of a course.
+##############################################
+##############################################
+# set_form_elements
+#
+# Generates javascript to set form elements to values based on
+# corresponding values for the same form elements when the page was
+# previously submitted.
+#
+# Last submission values are read from hidden form elements in referring
+# page which have the same name, i.e., generated by &echo_form_input().
+#
+# Intended to be called by onload event.
+#
+# Inputs:
+# (a) Reference to hash of echoed form elements to be set.
+#
+# In the hash, keys are the form element names, and the values are the
+# element type (selectbox, radio, checkbox or text -for textbox, textarea or
+# hidden).
+#
+# (b) Optional reference to hash of stored elements to be set.
+#
+# If the page being displayed is a page which permits modification of
+# previously stored data, e.g., the first page in a multi-page submission,
+# then if stored is supplied, form elements will be set to the last stored
+# values. If user supplied values are also available for the same elements
+# these will replace the stored values.
+#
+# Output:
+#
+# javascript function - set_form_elements() which sets form elements,
+# expects an argument: formname - the name of the form according to
+# the DOM, e.g., document.compose
+
+sub set_form_elements {
+ my ($elements,$stored) = @_;
+ my %values;
+ my $output .= 'function setFormElements(courseForm) {
+';
+ if (defined($stored)) {
+ foreach my $name (keys(%{$stored})) {
+ if (exists($$elements{$name})) {
+ if (ref($$stored{$name}) eq 'ARRAY') {
+ $values{$name} = $$stored{$name};
+ } else {
+ @{$values{$name}} = ($$stored{$name});
+ }
+ }
+ }
+ }
-The form element name is 'Section'. @$sections is sorted prior to output.
+ foreach my $key (keys(%env)) {
+ if ($key =~ /^form\.(.+)$/) {
+ my $name = $1;
+ if (exists($$elements{$name})) {
+ @{$values{$name}} = &Apache::loncommon::get_env_multiple($key);
+ }
+ }
+ }
-=cut
+ foreach my $name (keys(%values)) {
+ for (my $i=0; $i<@{$values{$name}}; $i++) {
+ $values{$name}[$i] = &HTML::Entities::decode($values{$name}[$i],'<>&"');
+ $values{$name}[$i] =~ s/([\r\n\f]+)/\\n/g;
+ $values{$name}[$i] =~ s/"/\\"/g;
+ }
+ if (($$elements{$name} eq 'text') || ($$elements{$name} eq 'hidden')) {
+ my $numvalues = @{$values{$name}};
+ if ($numvalues > 1) {
+ my $valuestring = join('","',@{$values{$name}});
+ $output .= qq|
+ var textvalues = new Array ("$valuestring");
+ var total = courseForm.elements['$name'].length;
+ if (total > $numvalues) {
+ total = $numvalues;
+ }
+ for (var i=0; i{$key}';\n".
+ " }\n";
+ }
+ }
+ $turninpathtext .= " return '';\n";
+ if (ref($multiples) eq 'HASH') {
+ foreach my $key (sort(keys(%{$multiples}))) {
+ $multtext .= " if (prefix == '$key') {\n".
+ " return '$multiples->{$key}';\n".
+ " }\n";
+ }
+ }
+ $multtext .= " return '';\n";
- foreach (sort @$sections) {
- $Str .= '
+// -1) {
+ if (formname.elements[idx].value != 'yes') {
+ submitterval = formname.elements[idx].value;
+ submitter = submitterval.replace(/^part_/,'');
+ subprefix = allprefixes[k];
+ result = overwritten_check(formname,path,multiresp,submitter,subprefix);
+ alloverwrites.push.apply(alloverwrites,result['overwrite']);
+ alldelconfirm.push.apply(alldelconfirm,result['delete']);
+ break;
+ }
+ }
+ }
+ if (submitter == '' || submitter == undefined) {
+ for (var m=0; m'."\n";
}
- $Str .= ''."\n";
-
- return $Str;
+ if (alloverwrites.length > 0) {
+ if (!confirm("$overwritewarn")) {
+ for (var n=0; n 0) {
+ if (!confirm("$delfilewarn")) {
+ for (var p=0; p 0) {
+ if ((formname.elements[alluploads[j]].value != undefined) &&
+ (formname.elements[alluploads[j]].value != '')) {
+ var filepath = formname.elements[alluploads[j]].value;
+ var newfilename = fnametrim.exec(filepath);
+ if (newfilename != null) {
+ var filename = String(newfilename);
+ var nospaces = filename.replace(/\\s+/g,'_');
+ var nospecials = nospaces.replace(/[^\\/\\w\\.\\-]/g,'');
+ var cleanfilename = nospecials.replace(/\\.(\\d+\\.)/g,"_\$1");
+ if (cleanfilename != '') {
+ var fullpath = path+"/"+cleanfilename;
+ if (multiresp == 1) {
+ var partid = String(alluploads[i]);
+ var subdir = partid.replace(/^\\d*.?\\d*_?HWFILE/,'');
+ if (subdir != "" && subdir != undefined) {
+ fullpath = path+"/"+subdir+"/"+cleanfilename;
+ }
+ }
+ for (var m=0; m 0) {
+ if (allskipdel.length > 0) {
+ for (var n=0; n and complete and
-as well as a
-=cut
+$arrayindexofjs
-########################################################
-########################################################
-sub Title {
- my ($pageName)=@_;
+ENDSCRIPT
+}
- my $Str = '';
+##############################################
+##############################################
+
+sub resize_scrollbox_js {
+ my ($context,$tabidstr,$tid) = @_;
+ my (%names,$paddingwfrac,$offsetwfrac,$offsetv,$minw,$minv);
+ if ($context eq 'docs') {
+ %names = (
+ boxw => 'contenteditor',
+ item => 'contentlist',
+ header => 'uploadfileresult',
+ scroll => 'contentscroll',
+ boxh => 'contenteditor',
+ );
+ $paddingwfrac = 0.09;
+ $offsetwfrac = 0.015;
+ $offsetv = 20;
+ $minw = 250;
+ $minv = 200;
+ } elsif ($context eq 'params') {
+ %names = (
+ boxw => 'parameditor',
+ item => 'mapmenuinner',
+ header => 'parmstep1',
+ scroll => 'mapmenuscroll',
+ boxh => 'parmlevel',
+ );
+ $paddingwfrac = 0.2;
+ $offsetwfrac = 0.015;
+ $offsetv = 80;
+ $minw = 100;
+ $minv = 100;
+ }
+ my $viewport_js = &Apache::loncommon::viewport_geometry_js();
+ my $output = '
+
+window.onresize=callResize;
+
+';
+ if ($context eq 'docs') {
+ if ($env{'form.active'}) {
+ $output .= "\nvar activeTab = '$env{'form.active'}$tid';\n";
+ } else {
+ $output .= "\nvar activeTab = '';\n";
+ }
+ }
+ $output .= <<"FIRST";
- $Str .= ''.$pageName.''."\n";
- $Str .= &Apache::loncommon::bodytag($pageName)."\n";
- $Str .= ''."\n";
+$viewport_js
- return $Str;
+function resize_scrollbox(scrollboxname,chkw,chkh) {
+ var scrollboxid = 'div_'+scrollboxname;
+ var scrolltableid = 'table_'+scrollboxname;
+ var scrollbox;
+ var scrolltable;
+ var ismobile = '$env{'browser.mobile'}';
+
+ if (document.getElementById("$names{'boxw'}") == null) {
+ return;
+ }
+
+ if (document.getElementById(scrollboxid) == null) {
+ return;
+ } else {
+ scrollbox = document.getElementById(scrollboxid);
+ }
+
+
+ if (document.getElementById(scrolltableid) == null) {
+ return;
+ } else {
+ scrolltable = document.getElementById(scrolltableid);
+ }
+
+ init_geometry();
+ var vph = Geometry.getViewportHeight();
+ var vpw = Geometry.getViewportWidth();
+
+FIRST
+ if ($context eq 'docs') {
+ $output .= "
+ var alltabs = ['$tabidstr'];
+";
+ } elsif ($context eq 'params') {
+ $output .= "
+ if (document.getElementById('$names{'boxh'}') == null) {
+ return;
+ }
+";
+ }
+ $output .= <<"SECOND";
+ var listwchange;
+ var scrollchange;
+ if (chkw == 1) {
+ var boxw = document.getElementById("$names{'boxw'}").offsetWidth;
+ var itemw;
+ var itemid = document.getElementById("$names{'item'}");
+ if (itemid != null) {
+ itemw = itemid.offsetWidth;
+ }
+ var itemwstart = itemw;
+
+ var scrollboxw = scrollbox.offsetWidth;
+ var scrollboxscrollw = scrollbox.scrollWidth;
+ var scrollstart = scrollboxw;
+
+ var offsetw = parseInt(vpw * $offsetwfrac);
+ var paddingw = parseInt(vpw * $paddingwfrac);
+
+ var minscrollboxw = $minw;
+ var maxcolw = 0;
+SECOND
+ if ($context eq 'docs') {
+ $output .= <<"DOCSONE";
+ var actabw = 0;
+ for (var i=0; i maxcolw) {
+ maxcolw = actabw;
+ }
+ } else {
+ if (document.getElementById(alltabs[i]) != null) {
+ var thistab = document.getElementById(alltabs[i]);
+ thistab.style.visibility = 'hidden';
+ thistab.style.display = 'block';
+ var tabw = document.getElementById(alltabs[i]).offsetWidth;
+ thistab.style.display = 'none';
+ thistab.style.visibility = '';
+ if (tabw > maxcolw) {
+ maxcolw = tabw;
+ }
+ }
+ }
+ }
+DOCSONE
+ } elsif ($context eq 'params') {
+ $output .= <<"PARAMSONE";
+ var parmlevelrows = new Array();
+ var mapmenucells = new Array();
+ parmlevelrows = document.getElementById("$names{'boxh'}").rows;
+ var numrows = parmlevelrows.length;
+ if (numrows > 1) {
+ mapmenucells = parmlevelrows[2].getElementsByTagName('td');
+ }
+ maxcolw = mapmenucells[0].offsetWidth;
+PARAMSONE
+ }
+ $output .= <<"THIRD";
+ if (maxcolw > 0) {
+ var newscrollboxw;
+ if (maxcolw+paddingw+scrollboxscrollw scrollboxheight) {
+ if (freevspace > offsetv) {
+ newscrollboxheight = scrollboxheight+freevspace-offsetv;
+ if (newscrollboxheight < minvscrollbox) {
+ newscrollboxheight = minvscrollbox;
+ }
+ scrollbox.style.height = newscrollboxheight+"px";
+ }
+ }
+ }
+ scrollboxheight = scrollbox.offsetHeight;
+ var itemh = document.getElementById("$names{'item'}").offsetHeight;
+
+ if (scrollboxscrollheight <= scrollboxheight) {
+ if ((itemh+offsetv)&');
+ if ($symb) {
+ $cfile .= '&symb='.&HTML::Entities::encode($symb,'"<>&');
+ } elsif ($folderpath) {
+ $cfile .= '&folderpath='.&HTML::Entities::encode($folderpath,'"<>&');
+ }
+ if ($forceedit) {
+ $cfile .= '&forceedit=1';
+ }
+ if ($forcereg) {
+ $cfile .= '®ister=1';
+ }
+ $jscall = "need_switchserver('".&Apache::loncommon::escape_single($cfile)."');";
+ }
+ } else {
+ unless ($cfile =~ m{^/priv/}) {
+ if ($cfile =~ m{^(/adm/wrapper/ext/[^#]+)#([^#]+)$}) {
+ $cfile = $1;
+ $anchor = $2;
+ }
+ if ($symb) {
+ if ($anchor ne '') {
+ if ($symb =~ m{^([^#]+)\Q#$anchor\E$}) {
+ $symb = $1.&escape(&escape('#')).$anchor;
+ }
+ }
+ $cfile .= (($cfile=~/\?/)?'&':'?')."symb=$symb";
+ } elsif ($folderpath) {
+ $cfile .= (($cfile=~/\?/)?'&':'?').
+ 'folderpath='.&HTML::Entities::encode(&escape($folderpath),'"<>&');
+ if ($title) {
+ $cfile .= (($cfile=~/\?/)?'&':'?').
+ 'title='.&HTML::Entities::encode(&escape($title),'"<>&');
+ }
+ if ($idx) {
+ $cfile .= (($cfile=~/\?/)?'&':'?').'idx='.$idx;
+ }
+ if ($suppurl) {
+ $cfile .= (($cfile=~/\?/)?'&':'?').
+ 'suppurl='.&HTML::Entities::encode(&escape($suppurl));
+ }
+ }
+ if ($forceedit) {
+ $cfile .= (($cfile=~/\?/)?'&':'?').'forceedit=1';
+ }
+ if ($forcereg) {
+ $cfile .= (($cfile=~/\?/)?'&':'?').'register=1';
+ }
+ if ($todocs) {
+ $cfile .= (($cfile=~/\?/)?'&':'?').'todocs=1';
+ }
+ if ($suppanchor ne '') {
+ $cfile .= (($cfile=~/\?/)?'&':'?').'anchor='.
+ &HTML::Entities::encode($suppanchor,'"<>&');
+ }
+ }
+ if ($anchor ne '') {
+ $cfile .= '#'.$anchor;
+ }
+ $jscall = "go('".&Apache::loncommon::escape_single($cfile)."')";
+ }
+ return $jscall;
+}
+
+##############################################
+##############################################
-$headings: The names of the headings for the student information
+# javascript_valid_email
+#
+# Generates javascript to validate an e-mail address.
+# Returns a javascript function which accetps a form field as argumnent, and
+# returns false if field.value does not satisfy two regular expression matches
+# for a valid e-mail address. Backwards compatible with old browsers without
+# support for javascript RegExp (just checks for @ in field.value in this case).
+
+sub javascript_valid_email {
+ my $scripttag .= <<'END';
+function validmail(field) {
+ var str = field.value;
+ if (window.RegExp) {
+ var reg1str = "(@.*@)|(\\.\\.)|(@\\.)|(\\.@)|(^\\.)";
+ var reg2str = "^.+\\@(\\[?)[a-zA-Z0-9\\-\\.]+\\.([a-zA-Z]{2,3}|[0-9]{1,3})(\\]?)$"; //"
+ var reg1 = new RegExp(reg1str);
+ var reg2 = new RegExp(reg2str);
+ if (!reg1.test(str) && reg2.test(str)) {
+ return true;
+ }
+ return false;
+ }
+ else
+ {
+ if(str.indexOf("@") >= 0) {
+ return true;
+ }
+ return false;
+ }
+}
+END
+ return $scripttag;
+}
-$spacePadding: The spaces to go between columns
-Output: $Str
+# USAGE: htmltag(element, content, {attribute => value,...});
+#
+# EXAMPLES:
+# - htmltag('a', 'this is an anchor', {href => 'www.example.com',
+# title => 'this is a title'})
+#
+# - You might want to set up needed tags like:
+#
+# my $h3 = sub { return htmltag( "h3", @_ ) };
+#
+# ... and use them: $h3->("This is a headline")
+#
+# - To set up a couple of tags, see sub inittags
+#
+# NOTES:
+# - Empty elements, such as are correctly terminated,
+# i.e. htmltag('br') returns
+# - Empty attributes (title="") are filtered out.
+# - The function will not check for deprecated attributes.
+#
+# OUTPUT: content enclosed in xhtml conform tags
+sub htmltag{
+ return
+ qq|<$_[0]|
+ . join( '', map { qq| $_="${$_[2]}{$_}"| if ${$_[2]}{$_} } keys(%{ $_[2] }) )
+ . ($_[1] ? qq|>$_[1]$_[0]>| : qq|/>|). "\n";
+};
-$Str: A formatted string of the table column headings.
+
+# USAGE: inittags(@tags);
+#
+# EXAMPLES:
+# - my ($h1, $h2, $h3) = inittags( qw( h1 h2 h3 ) )
+# $h1->("This is a headline") #Returns:
This is a headline
+#
+# NOTES: See sub htmltag for further information.
+#
+# OUTPUT: List of subroutines.
+sub inittags {
+ my @tags = @_;
+ return map { my $tag = $_;
+ sub { return htmltag( $tag, @_ ) }
+ } @tags;
+}
+
+
+# USAGE: scripttag(scriptcode, [start|end|both]);
+#
+# EXAMPLES:
+# - scripttag("alert('Hello World!')", 'both')
+# returns:
+#
+#
+# NOTES:
+# - works currently only for javascripts
+#
+# OUTPUT:
+# Scriptcode properly enclosed in ");
+Returns: HTML code with function list end
- my %prog_state;
- $prog_state{'done'}=0;
- $prog_state{'firststart'}=time;
- $prog_state{'laststart'}=time;
- $prog_state{'max'}=$number_to_do;
+=cut
- $r->rflush();
- return %prog_state;
+sub end_funclist {
+ return "\n";
}
-# update progress
-sub Update_PrgWin {
- my ($r,$prog_state,$displayString)=@_;
- $r->print('');
- $$prog_state{'laststart'}=time;
- $r->rflush();
-}
+=pod
-# increment progress state
-sub Increment_PrgWin {
- my ($r,$prog_state,$extraInfo)=@_;
- $$prog_state{'done'}++;
- my $time_est= (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.' minutes';
- if ($sec > 1) {
- $time_est.= ', '.$sec.' seconds';
- } elsif ($sec > 0) {
- $time_est.= ', '.$sec.' second';
- }
- } else {
- $time_est .= ' seconds';
- }
+=item &funclist_from_array( \@array, {legend => 'text for legend'} )
- $r->print('');
- $$prog_state{'laststart'}=time;
- $r->rflush();
-}
+Constructs a XHTML list from \@array with the first item being visually
+highlighted and set to the value of legend or 'Functions' if legend is
+empty.
-# close Progress Line
-sub Close_PrgWin {
- my ($r,$prog_state)=@_;
- $r->print(''."\n");
- undef(%$prog_state);
- $r->rflush();
+=over
+
+=item \@array
+
+A reference to the array containing text that will be wrapped in tags.
+
+=item { legend => 'text' }
+
+A string that's used as visually highlighted first item. 'Functions' is used if
+it's value evaluates to false.
+
+=back
+
+returns: XHTML list as string.
+
+=back
+
+=cut
+
+sub funclist_from_array {
+ my ($items, $args) = @_;
+ return unless(ref($items) eq 'ARRAY');
+ $args->{legend} ||= mt('Functions');
+ return list_from_array( [$args->{legend}, @$items],
+ { listattr => {class => 'LC_funclist'} });
+}
+
+=pod
+
+=over
+
+=item &actionbox( \@array )
+
+Constructs a XHTML list from \@array with the first item being visually
+highlighted and set to the value 'Actions'. The list is wrapped in a division.
+
+The actionlist is used to offer contextual actions, mostly at the bottom
+of a page, on which the outcome of an processed action is shown,
+e.g. a file operation in Authoring Space.
+
+=over
+
+=item \@array
+
+A reference to the array containing text. Details: sub funclist_from_array
+
+=back
+
+Returns: XHTML div as string.
+
+=back
+
+=cut
+
+sub actionbox {
+ my ($items) = @_;
+ return unless(ref($items) eq 'ARRAY');
+ return
+ '
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.