--- loncom/interface/lonhtmlcommon.pm	2006/07/21 08:59:30	1.145
+++ loncom/interface/lonhtmlcommon.pm	2007/11/06 04:39:19	1.169
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # a pile of common html routines
 #
-# $Id: lonhtmlcommon.pm,v 1.145 2006/07/21 08:59:30 albertel Exp $
+# $Id: lonhtmlcommon.pm,v 1.169 2007/11/06 04:39:19 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -60,7 +60,6 @@ use Time::Local;
 use Time::HiRes;
 use Apache::lonlocal;
 use Apache::lonnet;
-use lib '/home/httpd/lib/perl/';
 use LONCAPA;
 
 ##############################################
@@ -78,7 +77,7 @@ use LONCAPA;
 sub authorbombs {
     my $url=shift;
     $url=&Apache::lonnet::declutter($url);
-    my ($udom,$uname)=($url=~/^(\w+)\/(\w+)\//);
+    my ($udom,$uname)=($url=~m{^($LONCAPA::domain_re)/($LONCAPA::username_re)/});
     my %bombs=&Apache::lonmsg::all_url_author_res_msg($uname,$udom);
     foreach (keys %bombs) {
 	if ($_=~/^$udom\/$uname\//) {
@@ -141,6 +140,7 @@ sub select_recent {
     foreach my $value (sort(keys(%recent))) {
 	unless ($value =~/^error\:/) {
 	    my $escaped = &Apache::loncommon::escape_url($value);
+	    &Apache::loncommon::inhibit_menu_check(\$escaped);
 	    $return.="\n<option value='$escaped'>".
 		&unescape((split(/\&/,$recent{$value}))[1]).
 		'</option>';
@@ -481,6 +481,19 @@ ENDJS
     return $result;
 }
 
+
+sub build_url {
+    my ($base, $fields)=@_;
+    my $url;
+    $url = $base.'?';
+    foreach my $key (keys(%$fields)) {
+        $url.=&escape($key).'='.&escape($$fields{$key}).'&amp;';
+    }
+    $url =~ s/&amp;$//;
+    return $url;
+}
+
+
 ##############################################
 ##############################################
 
@@ -682,23 +695,18 @@ Returns: a perl string as described.
 ##############################################
 ##############################################
 sub StatusOptions {
-    my ($status, $formName,$size,$onchange)=@_;
+    my ($status, $formName,$size,$onchange,$mult)=@_;
     $size = 1 if (!defined($size));
     if (! defined($status)) {
         $status = 'Active';
         $status = $env{'form.Status'} if (exists($env{'form.Status'}));
     }
 
-    my $OpSel1 = '';
-    my $OpSel2 = '';
-    my $OpSel3 = '';
-
-    if($status eq 'Any')         { $OpSel3 = ' selected'; }
-    elsif($status eq 'Expired' ) { $OpSel2 = ' selected'; }
-    else                         { $OpSel1 = ' selected'; }
-
     my $Str = '';
     $Str .= '<select name="Status"';
+    if (defined($mult)){
+        $Str .= ' multiple="multiple" ';
+    }
     if(defined($formName) && $formName ne '' && ! defined($onchange)) {
         $Str .= ' onchange="document.'.$formName.'.submit()"';
     }
@@ -707,12 +715,18 @@ sub StatusOptions {
     }
     $Str .= ' size="'.$size.'" ';
     $Str .= '>'."\n";
-    $Str .= '<option value="Active" '.$OpSel1.'>'.
-        &mt('Currently Enrolled').'</option>'."\n";
-    $Str .= '<option value="Expired" '.$OpSel2.'>'.
-        &mt('Previously Enrolled').'</option>'."\n";
-    $Str .= '<option value="Any" '.$OpSel3.'>'.
-        &mt('Any Enrollment Status').'</option>'."\n";
+    foreach my $type (['Active',  &mt('Currently Has Access')],
+		      ['Future',  &mt('Will Have Future Access')],
+		      ['Expired', &mt('Previously Had Access')],
+		      ['Any',     &mt('Any Access Status')]) {
+	my ($name,$label) = @$type;
+	$Str .= '<option value="'.$name.'" ';
+	if ($status eq $name) {
+	    $Str .= 'selected="selected" ';
+	}
+	$Str .= '>'.$label.'</option>'."\n";
+    }
+
     $Str .= '</select>'."\n";
 }
 
@@ -855,7 +869,7 @@ sub Create_PrgWin {
          popwin=open(\'\',\'popwin\',\'width=400,height=100\');".
         "popwin.document.writeln(\'".$start_page.
               "<h4>$heading<\/h4>".
-              "<form name=\"popremain\" method=\"post\">".
+              "<form action= \"\" name=\"popremain\" method=\"post\">".
               '<input type="text" size="'.$width.'" name="remaining" value="'.
 	      &mt('Starting').'" /><\\/form>'.$end_page.
               "\');".
@@ -867,7 +881,7 @@ sub Create_PrgWin {
 	$prog_state{'window'}='window';
 	if (!$formname) {
 	    $prog_state{'formname'}=&get_uniq_name();
-	    &r_print($r,'<form name="'.$prog_state{'formname'}.'">');
+	    &r_print($r,'<form action="" name="'.$prog_state{'formname'}.'">');
 	} else {
 	    $prog_state{'formname'}=$formname;
 	}
@@ -894,7 +908,7 @@ sub Create_PrgWin {
 # update progress
 sub Update_PrgWin {
     my ($r,$prog_state,$displayString)=@_;
-    &r_print($r,'<script>'.$$prog_state{'window'}.'.document.'.
+    &r_print($r,'<script type="text/javascript">'.$$prog_state{'window'}.'.document.'.
 	     $$prog_state{'formname'}.'.'.
 	     $$prog_state{'inputname'}.'.value="'.
 	     $displayString.'";</script>');
@@ -1005,18 +1019,23 @@ sub crumbs {
 		} 
 	    } else {
 		$path.='/'; 
+	    }	    
+            my $href_path = &HTML::Entities::encode($path,'<>&"');
+	    &Apache::loncommon::inhibit_menu_check(\$href_path);
+	    if ($form) {
+	        my $href = 'javascript:'.$form.".action='".$href_path."';".$form.'.submit();';
+	        $output.=qq{<a href="$href" $target>$dir</a>/};
+	    } else {
+	        $output.=qq{<a href="$href_path" $target>$dir</a>/};
 	    }
-            my $linkpath = &Apache::loncommon::escape_single($path);
-            if ($form) {
-		$linkpath=
-                    qq{javascript:$form.action='$linkpath';$form.submit();};
-            }
-	    $output.=qq{<a href="$linkpath" $target>$dir</a>/};
 	}
     } else {
-	$output.=$uri;
+	foreach my $dir (split('/',$uri)) {
+            if (! $dir) { next; }
+	    $output.=$dir.'/';
+	}
     }
-    unless ($uri=~/\/$/) { $output=~s/\/$//; }
+    if ($uri !~ m|/$|) { $output=~s|/$||; }
     return $output.'</font>'.($noformat?'':'</b></tt><br />');
 }
 
@@ -1045,7 +1064,7 @@ var checkwin;
 function spellcheckerwindow(string) {
     var esc_string = string.replace(/\"/g,'&quot;');
     checkwin=window.open($nothing,'spellcheckwin','height=320,width=280,resizable=yes,scrollbars=yes,location=no,menubar=no,toolbar=no');
-    checkwin.document.writeln('$start_page<form name="spellcheckform" action="/adm/spellcheck" method="post"><input type="hidden" name="text" value="'+esc_string+'" /><\/form>$end_page');
+    checkwin.document.writeln('$start_page<form name="spellcheckform" action="/adm/spellcheck" method="post"><input type="hidden" name="text" value="'+esc_string+'" /><\\/form>$end_page');
     checkwin.document.close();
 }
 // END LON-CAPA Internal -->
@@ -1082,45 +1101,13 @@ ENDLINK
 }
 
 sub htmlareaheaders {
-    if (&htmlareablocked()) { return ''; }
-    unless (&htmlareabrowser()) { return ''; }
-    my $lang='en';
-    if (&mt('htmlarea_lang') ne 'htmlarea_lang') {
-	$lang=&mt('htmlarea_lang');
-    }
+    return if (&htmlareablocked());
+    return if (!&htmlareabrowser());
     return (<<ENDHEADERS);
-<script type="text/javascript">
-_editor_url='/htmlarea/';
-_editor_lang='$lang';
-</script>
-<script type="text/javascript" src="/htmlarea/htmlarea.js"></script>
+<script type="text/javascript" src="/fckeditor/fckeditor.js"></script>
 ENDHEADERS
 }
 
-# ------------------------------------------------- Activate additional buttons
-
-sub htmlareaaddbuttons {
-    if (&htmlareablocked()) { return ''; }
-    unless (&htmlareabrowser()) { return ''; }
-    return (<<ENDADDBUTTON);
-    var config=new HTMLArea.Config();
-    config.registerButton('ed_math','LaTeX Inline',
-			  '/htmlarea/images/ed_math.gif',false,
-			    function(editor,id) {
-			      editor.surroundHTML('&nbsp;<m>\$','\$</m>&nbsp;');
-			    }
-			  );
-    config.registerButton('ed_math_eqn','LaTeX Equation',
-			  '/htmlarea/images/ed_math_eqn.gif',false,
-			    function(editor,id) {
-			      editor.surroundHTML(
-				     '&nbsp;\\n<center><m>\\\\[','\\\\]</m></center>\\n&nbsp;');
-			    }
-			  );
-    config.toolbar.push(['ed_math','ed_math_eqn']);
-ENDADDBUTTON
-}
-
 # ----------------------------------------------------------------- Preferences
 
 sub disablelink {
@@ -1139,16 +1126,33 @@ sub enablelink {
     return '<a href="'.&HTML::Entities::encode('/adm/preferences?action=set_wysiwyg&wysiwyg=on&returnurl=','<>&"').&escape($ENV{'REQUEST_URI'}).'">'.&mt('Enable WYSIWYG Editor').'</a>';
 }
 
+# ------------------------------------------------- lang to use in html editor
+sub htmlarea_lang {
+    my $lang='en';
+    if (&mt('htmlarea_lang') ne 'htmlarea_lang') {
+	$lang=&mt('htmlarea_lang');
+    }
+    return $lang;
+}
+
 # ----------------------------------------- Script to activate only some fields
 
 sub htmlareaselectactive {
     my @fields=@_;
     unless (&htmlareabrowser()) { return ''; }
     if (&htmlareablocked()) { return '<br />'.&enablelink(@fields); }
-    my $output='<script type="text/javascript" defer="1">'.
-	&htmlareaaddbuttons();
-    foreach(@fields) {
-	$output.="\nHTMLArea.replace('$_',config);";
+    my $output='<script type="text/javascript" defer="1">';
+    my $lang = &htmlarea_lang();
+    foreach my $field (@fields) {
+	$output.="
+{
+    var oFCKeditor = new FCKeditor('$field');
+    oFCKeditor.Config['CustomConfigurationsPath'] = 
+	'/fckeditor/loncapaconfig.js';    
+    oFCKeditor.ReplaceTextarea();
+    oFCKeditor.Config['AutoDetectLanguage'] = false;
+    oFCKeditor.Config['DefaultLanguage'] = '$lang';
+}";
     }
     $output.="\nwindow.status='Activated Editfields';\n</script><br />".
 	&disablelink(@fields);
@@ -1201,7 +1205,8 @@ Pushes a breadcrumb on the stack of crum
 
 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.
+links to the FAQ and bug sites. If the key 'no_mt' is present the 'title' 
+and 'text' values won't be sent through &mt()
 
 returns: nothing    
 
@@ -1251,13 +1256,22 @@ returns: nothing
                      if (defined($_->{'target'}) && $_->{'target'} ne '') {
                          $result .= 'target="'.$_->{'target'}.'" ';
                      }
-                     $result .='title="'.&mt($_->{'title'}).'">'.
-                         &mt($_->{'text'}).'</a>';
+		     if ($_->{'no_mt'}) {
+			 $result .='title="'.$_->{'title'}.'">'.
+			     $_->{'text'}.'</a>';
+		     } else {
+			 $result .='title="'.&mt($_->{'title'}).'">'.
+			     &mt($_->{'text'}).'</a>';
+		     }
                      $result;
                      } @Crumbs
                  );
         $links .= '-&gt;' if ($links ne '');
-        $links .= '<b>'.&mt($last->{'text'}).'</b>';
+	if ($last->{'no_mt'}) {
+	    $links .= '<b>'.$last->{'text'}.'</b>';
+	} else {
+	    $links .= '<b>'.&mt($last->{'text'}).'</b>';
+	}
         #
         my $icons = '';
         $faq = $last->{'faq'} if (exists($last->{'faq'}));
@@ -1320,7 +1334,7 @@ returns: nothing
 # row2
 # row3   ... etc.
 # &submit_row(0
-# &end_pickbox()
+# &end_pick_box()
 #
 # where row1, row 2 etc. are chosen from &role_select_row,&course_select_row,
 # &status_select_row and &email_default_row
@@ -1417,7 +1431,7 @@ ENDTWO
 }
 
 sub role_select_row {
-    my ($roles,$title,$css_class) = @_;
+    my ($roles,$title,$css_class,$show_separate_custom,$cdom,$cnum) = @_;
     my $output;
     if (defined($title)) {
         $output = &row_title($title,$css_class);
@@ -1428,10 +1442,25 @@ sub role_select_row {
         my $plrole;
         if ($role eq 'ow') {
             $plrole = &mt('Course Owner');
+        } elsif ($role eq 'cr') {
+            if ($show_separate_custom) {
+                if ($cdom ne '' && $cnum ne '') {
+                    my %course_customroles = &course_custom_roles($cdom,$cnum);
+                    foreach my $crrole (sort(keys(%course_customroles))) {
+                        my ($plcrrole) = ($crrole =~ m|^cr/[^/]+/[^/]+/(.+)$|);
+                        $output .= '  <option value="'.$crrole.'">'.$plcrrole.
+                                   '</option>';
+                    }
+                }
+            } else {
+                $plrole = &mt('Custom Role');
+            }
         } else {
             $plrole=&Apache::lonnet::plaintext($role);
         }
-        $output .= '  <option value="'.$role.'">'.$plrole.'</option>';
+        if (($role ne 'cr') || (!$show_separate_custom)) {
+            $output .= '  <option value="'.$role.'">'.$plrole.'</option>';
+        }
     }
     $output .= qq|                </select>\n|;
     if (defined($title)) {
@@ -1444,7 +1473,14 @@ sub course_select_row {
     my ($title,$formname,$totcodes,$codetitles,$idlist,$idlist_titles,
 	$css_class) = @_;
     my $output = &row_title($title,$css_class);
-    $output .= qq|
+    $output .= &course_selection($formname,$totcodes,$codetitles,$idlist,$idlist_titles);
+    $output .= &row_closure();
+    return $output;
+}
+
+sub course_selection {
+    my ($formname,$totcodes,$codetitles,$idlist,$idlist_titles) = @_;
+    my $output = qq|
 <script type="text/javascript">
     function coursePick (formname) {
         for  (var i=0; i<formname.coursepick.length; i++) {
@@ -1517,8 +1553,7 @@ sub course_select_row {
             $output .= '</tr></table><br />';
         }
     }
-    $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";
-    $output .= &row_closure();
+    $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";
     return $output;
 }
 
@@ -1543,7 +1578,6 @@ sub status_select_row {
 sub email_default_row {
     my ($authtypes,$title,$descrip,$css_class) = @_;
     my $output = &row_title($title,$css_class);
-    my @rowcols = ('#eeeeee','#dddddd');
     $output .= $descrip.
 	&Apache::loncommon::start_data_table().
 	&Apache::loncommon::start_data_table_header_row().
@@ -1584,6 +1618,24 @@ sub submit_row {
     return $output;
 }
 
+sub course_custom_roles {
+    my ($cdom,$cnum) = @_;
+    my %returnhash=();
+    my %coursepersonnel=&Apache::lonnet::dump('nohist_userroles',$cdom,$cnum);
+    foreach my $person (sort(keys(%coursepersonnel))) {
+        my ($role) = ($person =~ /^([^:]+):/);
+        my ($end,$start) = split(/:/,$coursepersonnel{$person});
+        if ($end == -1 && $start == -1) {
+            next;
+        }
+        if ($role =~ m|^cr/[^/]+/[^/]+/[^/]|) {
+            $returnhash{$role} ++;
+        }
+    }
+    return %returnhash;
+}
+
+
 ##############################################
 ##############################################
                                                                              
@@ -1722,66 +1774,66 @@ sub set_form_elements {
                 my $valuestring = join('","',@{$values{$name}});
                 $output .= qq|
   var textvalues = new Array ("$valuestring");
-  var total = courseForm.$name.length;
+  var total = courseForm.elements['$name'].length;
   if (total > $numvalues) {
       total = $numvalues;
   }    
   for (var i=0; i<total; i++) {
-      courseForm.$name\[i].value = textvalues[i];
+      courseForm.elements['$name']\[i].value = textvalues[i];
   }
 |;
             } else {
                 $output .= qq|
-  courseForm.$name.value = "$values{$name}[0]";
+  courseForm.elements['$name'].value = "$values{$name}[0]";
 |;
             }
         } else {
             $output .=  qq|
-  var elementLength = courseForm.$name.length;
+  var elementLength = courseForm.elements['$name'].length;
   if (elementLength==undefined) {
 |;
             foreach my $value (@{$values{$name}}) {
                 if ($$elements{$name} eq 'selectbox') {
                     $output .=  qq|
-      if (courseForm.$name.options[0].value == "$value") {
-          courseForm.$name.options[0].selected = true;
+      if (courseForm.elements['$name'].options[0].value == "$value") {
+          courseForm.elements['$name'].options[0].selected = true;
       }|;
                 } elsif (($$elements{$name} eq 'radio') ||
                          ($$elements{$name} eq 'checkbox')) {
                     $output .= qq|
-      if (courseForm.$name.value == "$value") {
-          courseForm.$name.checked = true;
+      if (courseForm.elements['$name'].value == "$value") {
+          courseForm.elements['$name'].checked = true;
       }|;
                 }
             }
             $output .= qq|
   }
   else {
-      for (var i=0; i<courseForm.$name.length; i++) {
+      for (var i=0; i<courseForm.elements['$name'].length; i++) {
 |;
             if ($$elements{$name} eq 'selectbox') {
                 $output .=  qq|
-          courseForm.$name.options[i].selected = false;|;
+          courseForm.elements['$name'].options[i].selected = false;|;
             } elsif (($$elements{$name} eq 'radio') || 
                      ($$elements{$name} eq 'checkbox')) {
                 $output .= qq|
-          courseForm.$name\[i].checked = false;|; 
+          courseForm.elements['$name']\[i].checked = false;|; 
             }
             $output .= qq|
       }
-      for (var j=0; j<courseForm.$name.length; j++) {
+      for (var j=0; j<courseForm.elements['$name'].length; j++) {
 |;
             foreach my $value (@{$values{$name}}) {
                 if ($$elements{$name} eq 'selectbox') {
                     $output .=  qq|
-          if (courseForm.$name.options[j].value == "$value") {
-              courseForm.$name.options[j].selected = true;
+          if (courseForm.elements['$name'].options[j].value == "$value") {
+              courseForm.elements['$name'].options[j].selected = true;
           }|;
                 } elsif (($$elements{$name} eq 'radio') ||
                          ($$elements{$name} eq 'checkbox')) { 
                       $output .= qq|
-          if (courseForm.$name\[j].value == "$value") {
-              courseForm.$name\[j].checked = true;
+          if (courseForm.elements['$name']\[j].value == "$value") {
+              courseForm.elements['$name']\[j].checked = true;
           }|;
                 }
             }
@@ -1796,6 +1848,43 @@ sub set_form_elements {
     return $output;
 }
 
+##############################################
+##############################################
+
+# 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;
+}
+
 1;
 
 __END__