--- loncom/homework/functionplotresponse.pm	2010/11/23 23:55:01	1.46
+++ loncom/homework/functionplotresponse.pm	2011/11/19 23:35:25	1.77
@@ -1,7 +1,7 @@
 # LearningOnline Network with CAPA
-# option list style responses
+# Functionplot responses
 #
-# $Id: functionplotresponse.pm,v 1.46 2010/11/23 23:55:01 www Exp $
+# $Id: functionplotresponse.pm,v 1.77 2011/11/19 23:35:25 www Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -31,9 +31,11 @@ use strict;
 use Apache::response();
 use Apache::lonlocal;
 use Apache::lonnet;
+use Apache::run;
  
 BEGIN {
   &Apache::lonxml::register('Apache::functionplotresponse',('functionplotresponse','backgroundplot','spline',
+                                                            'plotobject','plotvector','functionplotvectorrule','functionplotvectorsumrule',
                                                             'functionplotrule','functionplotruleset',
                                                             'functionplotelements'));
 }
@@ -61,7 +63,7 @@ sub geogebra_endcode {
 #
 sub geogebra_spline_program {
     return (<<ENDSPLINEPROGRAM);
-<param name="ggbBase64" value="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" />
+<param name="ggbBase64" value="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"/>
 ENDSPLINEPROGRAM
 }
 
@@ -74,8 +76,8 @@ sub geogebra_default_parameters {
         <param name="image" value="/adm/lonIcons/lonanim.gif"  />
         <param name="boxborder" value="false"  />
         <param name="centerimage" value="true"  />
-	<param name="cache_archive" value="geogebra.jar, geogebra_main.jar, geogebra_gui.jar, geogebra_cas.jar, geogebra_algos.jar, geogebra_export.jar, geogebra_javascript.jar, jlatexmath.jar, jlm_greek.jar, jlm_cyrillic.jar, geogebra_properties.jar" />
-	<param name="cache_version" value="3.9.115.0, 3.9.115.0, 3.9.115.0, 3.9.115.0, 3.9.115.0, 3.9.115.0, 3.9.115.0, 3.9.115.0, 3.9.115.0, 3.9.115.0, 3.9.115.0" />
+	<param name="cache_archive" value="geogebra.jar, geogebra_main.jar, geogebra_gui.jar, geogebra_cas.jar, geogebra_export.jar, geogebra_algos.jar, geogebra_javascript.jar, geogebra_properties.jar, jlatexmath.jar, jlm_cyrillic.jar, jlm_greek.jar" />
+	<param name="cache_version" value="4.0.1.0,4.0.1.0,4.0.1.0,4.0.1.0,4.0.1.0,4.0.1.0,4.0.1.0,4.0.1.0,4.0.1.0,4.0.1.0,4.0.1.0" />
         <param name="framePossible" value="false" />
 
         <param name="showResetIcon" value="false" />
@@ -108,7 +110,7 @@ sub init_script {
           $script.="if (param=='applet_$id') { loaded_$id=true; }\n";
       }
       $script.="if (".join(' && ',map { "loaded_$_" } (@Apache::functionplotresponse::callscripts)).
-               ") { setTimeout('ggbInitAll()',20) }";
+               ") { setTimeout('ggbInitAll()',200) }";
       my $calls=join("\n",map { "ggbInit_$_();" } (@Apache::functionplotresponse::callscripts)); 
       return (<<ENDGGBINIT);
 <script type="text/javascript">
@@ -161,9 +163,19 @@ sub update_register {
 # Set a point coordinate variable
 #
 sub set_point_coordinate {
-   my ($id,$variable,$x,$y)=@_;
+   my ($id,$variable,$x,$y,$fixed)=@_;
+   my $mult=($fixed?'a*':'');
+# Get rid of wild exponents, make sure it's a number
+   $x=1.*$x;
+   $y=1.*$y;
+# GeoGebra does not understand "E"
+   $x=~s/[e|E]/\*10\^/;
+   $x=~s/\+//;
+   $y=~s/[e|E]/\*10\^/;
+   $y=~s/\+//;
    return (<<ENDSETVARIABLE);
-document.ggbApplet_$id.evalCommand("$variable=($x,$y)");
+document.ggbApplet_$id.evalCommand("a=1");
+document.ggbApplet_$id.evalCommand("$variable=$mult($x,$y)");
 document.ggbApplet_$id.setLabelVisible("$variable",false);
 ENDSETVARIABLE
 }
@@ -172,21 +184,23 @@ ENDSETVARIABLE
 # Set a slope coordinate variable
 #
 sub set_slope_coordinate {
-   my ($id,$variable,$xrel,$yrel,$xmin,$xmax,$ymin,$ymax,$pointname)=@_;
+   my ($id,$variable,$xrel,$yrel,$xmin,$xmax,$ymin,$ymax,$pointname,$fixed)=@_;
    my $xvariable=$variable.'x';
    my $yvariable=$variable.'y';
    my $domain=$xmax-$xmin;
    my $range=$ymax-$ymin;
    my $xinterval=$domain/100.;
    my $yinterval=$range/200.;
+   my $mult=($fixed?'a*':'');
    return (<<ENDSETSVARIABLE);
-document.ggbApplet_$id.evalCommand("$xvariable=Slider[0,$domain,$xinterval]");
+document.ggbApplet_$id.evalCommand("a=1");
+document.ggbApplet_$id.evalCommand("$xvariable=Slider[$xinterval,$domain,$xinterval]");
 document.ggbApplet_$id.setVisible("$xvariable", false);
 document.ggbApplet_$id.evalCommand("$xvariable=$xrel");
 document.ggbApplet_$id.evalCommand("$yvariable=Slider[-$range,$range,$yinterval]");
 document.ggbApplet_$id.setVisible("$yvariable", false);
 document.ggbApplet_$id.evalCommand("$yvariable=$yrel");
-document.ggbApplet_$id.evalCommand("$variable=($xvariable+x($pointname),$yvariable+y($pointname))");
+document.ggbApplet_$id.evalCommand("$variable=$mult($xvariable+x($pointname),$yvariable+y($pointname))");
 document.ggbApplet_$id.setLabelVisible("$variable", false);
 ENDSETSVARIABLE
 }
@@ -215,7 +229,7 @@ sub generate_input_field {
 # Initialize a new point coordinate variable at set a listener on it
 #
 sub new_point_coordinate {
-    my ($id,$variable,$x,$y)=@_;
+    my ($id,$variable,$x,$y,$fixed)=@_;
     if (defined($Apache::functionplotresponse::previous{&field_name($id,$variable,'x')})) {
        $x=$Apache::functionplotresponse::previous{&field_name($id,$variable,'x')};
     }
@@ -223,14 +237,14 @@ sub new_point_coordinate {
        $y=$Apache::functionplotresponse::previous{&field_name($id,$variable,'y')};
     }
     &generate_input_field($id,$variable,$x,$y);
-    return &set_point_coordinate($id,$variable,$x,$y).&update_register($id,$variable);
+    return &set_point_coordinate($id,$variable,$x,$y,$fixed).&update_register($id,$variable);
 }
 
 #
 # Initialize a new slope coordinate variable at set a listener on it
 #
 sub new_slope_coordinate {
-    my ($id,$variable,$x,$y,$pointname,$xp,$yp,$xmin,$xmax,$ymin,$ymax)=@_;
+    my ($id,$variable,$x,$y,$pointname,$xp,$yp,$xmin,$xmax,$ymin,$ymax,$fixed)=@_;
 #
 # $variable: name of the slope point
 # $x, $y: coordinates of the slope point
@@ -253,7 +267,7 @@ sub new_slope_coordinate {
     &generate_input_field($id,$variable,$x,$y);
     my $xrel=$x-$xp;
     my $yrel=$y-$yp;
-    return &set_slope_coordinate($id,$variable,$xrel,$yrel,$xmin,$xmax,$ymin,$ymax,$pointname).&update_register($id,$variable);
+    return &set_slope_coordinate($id,$variable,$xrel,$yrel,$xmin,$xmax,$ymin,$ymax,$pointname,$fixed).&update_register($id,$variable);
 }
 
 #
@@ -329,8 +343,12 @@ ENDYOFFAXISLABEL
     return $return;
 }
 
+#
+# Subroutine to produce background and answer plots
+#
+
 sub plot_script {
-   my ($id,$function,$fixed,$label,$color,$xmin,$xmax)=@_;
+   my ($id,$function,$fixed,$label,$color,$xmin,$xmax,$thickness)=@_;
    $label=~s/\W//g;
    if (($label) && ($label!~/^[A-Za-z]/)) {
       $label='C'.$label;
@@ -354,18 +372,95 @@ sub plot_script {
    if ($fixed) {
       return "document.ggbApplet_$id.evalCommand('$label=Function[$function,$xmin,$xmax]');\n".
              ($visible?'':"document.ggbApplet_$id.setLabelVisible('$label', false);\n").
-             ($color?"document.ggbApplet_$id.setColor('$label',$rc,$gc,$bc);\n":'');
+             ($color?"document.ggbApplet_$id.setColor('$label',$rc,$gc,$bc);\n":'').
+             ($thickness?"document.ggbApplet_$id.setLineThickness('$label',$thickness);\n":'');
    } else {
        return "document.ggbApplet_$id.evalCommand('y=$function');\n";
    }
 }
 
 #
+# Subroutine to produce objects
+#
+
+sub plotobject_script {
+   my ($id,$label,$x,$y)=@_;
+   unless ($label) {
+      $Apache::functionplotresponse::counter++;
+      $label='O'.$Apache::functionplotresponse::counter;
+   }
+   &generate_input_field($id,$label,$x,$y);
+   return "document.ggbApplet_$id.evalCommand('a=1');\n".
+          "document.ggbApplet_$id.setVisible('a', false);\n".
+          "document.ggbApplet_$id.setLabelVisible('a', false);\n".
+          "document.ggbApplet_$id.evalCommand('$label=a*($x,$y)');\n".
+          "document.ggbApplet_$id.setVisible('$label', true);\n".
+          "document.ggbApplet_$id.setLabelVisible('$label', true);\n";
+}
+
+#
+# Subroutine to produce vectors
+#
+
+sub plotvector_script {
+   my ($id,$label,$xs,$ys,$xe,$ye,$xmin,$xmax)=@_;
+   unless ($label) {
+      $Apache::functionplotresponse::counter++;
+      $label='V'.$Apache::functionplotresponse::counter;
+   }
+   my $startlabel=$label.'Start';
+   my $endlabel=$label.'End';
+   my $pointlabel=$label.'Point';
+   my $pointx=2.*($xmax-$xmin)+$xmax;
+   my $anglelabel=$label.'Angle';
+   return 
+       &new_point_coordinate($id,$startlabel,$xs,$ys,0).
+       &new_point_coordinate($id,$endlabel,$xe,$ye,0).
+       (<<ENDVECTOR);
+document.ggbApplet_$id.evalCommand("$label=Vector[$startlabel,$endlabel]");
+document.ggbApplet_$id.setLabelVisible("$label",true);
+document.ggbApplet_$id.setLineThickness("$label",8);
+document.ggbApplet_$id.evalCommand("$pointlabel=($pointx,y($startlabel))");
+document.ggbApplet_$id.evalCommand("$anglelabel=Angle[$pointlabel,$startlabel,$endlabel]");
+document.ggbApplet_$id.setLabelVisible("$anglelabel",true);
+document.ggbApplet_$id.setLabelStyle("$anglelabel",VALUE=2);
+ENDVECTOR
+}
+
+#
+# Answer spline display
+# 
+# points: x,y,slope_x,slope_y
+
+sub answer_spline_script {
+   my ($id,@points)=@_;
+   my $order=int(($#points+1)/4);
+   if ($order<2) { $order=2; }
+   if ($order>8) { $order=8; }
+   $Apache::functionplotresponse::counter++;
+   my $label='CSpline'.$Apache::functionplotresponse::counter;
+   my $output='document.ggbApplet_'.$id.'.evalCommand("'.$label.'=Spline'.$order.'[';
+   for (my $i=0;$i<=$#points;$i+=4) {
+      $output.="($points[$i],$points[$i+1]),($points[$i+2],$points[$i+3]),";
+   }
+   $output=~s/\,$//;
+   $output.=']");'."\n";
+   for (my $i=2; $i<2*$order; $i+=2) {
+       $output.='document.ggbApplet_'.$id.'.setColor("'.$label.'_'.($i>=10?'{':'').$i.($i>=10?'}':'').'",0,170,0);'."\n";
+   }
+   for (my $i=1; $i<2*$order; $i+=2) {
+       $output.='document.ggbApplet_'.$id.'.setVisible("'.$label.'_'.($i>=10?'{':'').$i.($i>=10?'}':'').'",false);'."\n";
+   }
+
+   return $output;
+}
+
+#
 # Subroutine that generates code for spline $label based on stored information
 #
 
 sub generate_spline {
-   my ($id,$label,$xmin,$xmax,$ymin,$ymax)=@_;
+   my ($id,$label,$xmin,$xmax,$ymin,$ymax,$fixed)=@_;
    my $result='';
    my $order=$Apache::functionplotresponse::splineorder{$label};
    my $x=$Apache::functionplotresponse::splineinitx{$label};
@@ -374,17 +469,120 @@ sub generate_spline {
    my $sy=$Apache::functionplotresponse::splinescaley{$label};
    my @coords=();
    foreach my $i (1..$order) {
-       $result.=&new_point_coordinate($id,$label.'P'.$i,$x,$y);
+       $result.=&new_point_coordinate($id,$label.'P'.$i,$x,$y,$fixed);
        my $xp=$x;
        $x+=$sx/(2.*($order-1));
        push(@coords,$label.'P'.$i);
-       $result.=&new_slope_coordinate($id,$label.'S'.$i,$x,$y+$sy,$label.'P'.$i,$xp,$y,$xmin,$xmax,$ymin,$ymax);
+       $result.=&new_slope_coordinate($id,$label.'S'.$i,$x,$y+$sy,$label.'P'.$i,$xp,$y,$xmin,$xmax,$ymin,$ymax,$fixed);
        $x+=$sx/(2.*($order-1));
        push(@coords,$label.'S'.$i);
    }
    $result.='document.ggbApplet_'.$id.'.evalCommand("Spline'.$order.'['.join(',',@coords).']");'."\n";
    return $result;
 }
+
+#
+# Object
+#
+
+sub start_plotobject {
+   my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
+   my $result='';
+   my $internalid = $Apache::inputtags::part.'_'.$Apache::inputtags::response[-1];
+   my $x=&Apache::lonxml::get_param('x',$parstack,$safeeval);
+   my $y=&Apache::lonxml::get_param('y',$parstack,$safeeval);
+   my $label=&Apache::lonxml::get_param('label',$parstack,$safeeval);
+   $label=~s/\W//gs;
+   $label=ucfirst($label);
+   unless ($label) { $label="NewObject"; }
+   if ($target eq 'web') {
+      my ($xmin,$xmax,$ymin,$ymax)=&boundaries($parstack,$safeeval,-3);
+      unless (defined($x)) { $x=$xmin; }
+      unless (defined($y)) { $y=$ymin; }
+      $result.=&plotobject_script($internalid,$label,$x,$y);
+   } elsif ($target eq 'edit') {
+        $result=&Apache::edit::tag_start($target,$token,'Plot Object').
+             &Apache::edit::text_arg('Label on Plot:','label',
+                                     $token,'16').
+             &Apache::edit::text_arg('x:','x',
+                                     $token,'8').
+             &Apache::edit::text_arg('y:','y',
+                                     $token,'8').
+             &Apache::edit::end_row();
+  } elsif ($target eq 'modified') {
+    $env{'form.'.&Apache::edit::html_element_name('label')}=ucfirst($env{'form.'.&Apache::edit::html_element_name('label')});
+    my $constructtag=&Apache::edit::get_new_args($token,$parstack,$safeeval,'label','x','y');
+    if ($constructtag) { $result=&Apache::edit::rebuild_tag($token); }
+  }
+  return $result;
+}
+
+sub end_plotobject {
+   my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
+   my $result='';
+   if ($target eq 'edit') {
+       $result=&Apache::edit::end_table();
+   }
+   return $result;
+}
+
+#
+# Vector
+#
+
+sub start_plotvector {
+   my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
+   my $result='';
+   my $internalid = $Apache::inputtags::part.'_'.$Apache::inputtags::response[-1];
+   my $tailx=&Apache::lonxml::get_param('tailx',$parstack,$safeeval);
+   my $taily=&Apache::lonxml::get_param('taily',$parstack,$safeeval);
+   my $tipx=&Apache::lonxml::get_param('tipx',$parstack,$safeeval);
+   my $tipy=&Apache::lonxml::get_param('tipy',$parstack,$safeeval);
+
+   my $label=&Apache::lonxml::get_param('label',$parstack,$safeeval);
+   $label=~s/\W//gs;
+   $label=ucfirst($label);
+   unless ($label) { $label="NewVector"; }
+   if ($target eq 'web') {
+      my ($xmin,$xmax,$ymin,$ymax)=&boundaries($parstack,$safeeval,-3);
+      unless (defined($tailx)) { $tailx=$xmin; }
+      unless (defined($taily)) { $taily=$ymin; }
+      unless (defined($tipx)) { $tipx=$xmin; }
+      unless (defined($tipy)) { $tipy=$ymin; }
+      $result.=&plotvector_script($internalid,$label,$tailx,$taily,$tipx,$tipy,$xmin,$xmax);
+   } elsif ($target eq 'edit') {
+        $result=&Apache::edit::tag_start($target,$token,'Plot Vector').
+             &Apache::edit::text_arg('Label on Plot:','label',
+                                     $token,'16').
+             &Apache::edit::text_arg('Tail x:','tailx',
+                                     $token,'8').
+             &Apache::edit::text_arg('Tail y:','taily',
+                                     $token,'8').
+             &Apache::edit::text_arg('Tip x:','tipx',
+                                     $token,'8').
+             &Apache::edit::text_arg('Tip y:','tipy',
+                                     $token,'8').
+
+             &Apache::edit::end_row();
+  } elsif ($target eq 'modified') {
+    $env{'form.'.&Apache::edit::html_element_name('label')}=ucfirst($env{'form.'.&Apache::edit::html_element_name('label')});
+    my $constructtag=&Apache::edit::get_new_args($token,$parstack,$safeeval,'label','tailx','taily','tipx','tipy');
+    if ($constructtag) { $result=&Apache::edit::rebuild_tag($token); }
+  }
+  return $result;
+}
+
+sub end_plotvector {
+   my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
+   my $result='';
+   if ($target eq 'edit') {
+       $result=&Apache::edit::end_table();
+   }
+   return $result;
+}
+
+
+
 #
 # <backgroundplot function="..." fixed="yes/no" />
 #
@@ -393,6 +591,8 @@ sub start_backgroundplot {
    my $result='';
    my $internalid = $Apache::inputtags::part.'_'.$Apache::inputtags::response[-1];
    my $function=&Apache::lonxml::get_param('function',$parstack,$safeeval);
+   my $xinitial=&Apache::lonxml::get_param('xinitial',$parstack,$safeeval);
+   my $xfinal=&Apache::lonxml::get_param('xfinal',$parstack,$safeeval);
    my $label=&Apache::lonxml::get_param('label',$parstack,$safeeval);
    my $color=&Apache::lonxml::get_param('color',$parstack,$safeeval);
    $color=~s/[^a-fA-F0-9]//gs;
@@ -402,11 +602,17 @@ sub start_backgroundplot {
    unless ($function) { $function="0"; }
    if ($target eq 'web') {
       my ($xmin,$xmax,$ymin,$ymax)=&boundaries($parstack,$safeeval,-3);
-      $result.=&plot_script($internalid,$function,$fixed,$label,$color,$xmin,$xmax);
+      unless (defined($xinitial)) { $xinitial=$xmin; }
+      unless (defined($xfinal)) { $xfinal=$xmax; }
+      $result.=&plot_script($internalid,$function,$fixed,$label,$color,$xinitial,$xfinal);
    } elsif ($target eq 'edit') {
         $result=&Apache::edit::tag_start($target,$token,'Background Function Plot').
              &Apache::edit::text_arg('Function:','function',
                                      $token,'16').
+             &Apache::edit::text_arg('Initial x-value (optional):','xinitial',
+                                     $token,'8').
+             &Apache::edit::text_arg('Final x-value (optional):','xfinal',
+                                     $token,'8').
              &Apache::edit::text_arg('Label on Plot:','label',
                                      $token,'8').
              &Apache::edit::text_arg('Color (hex code):','color',
@@ -416,7 +622,7 @@ sub start_backgroundplot {
              &Apache::edit::end_row();
   } elsif ($target eq 'modified') {
     my $constructtag=&Apache::edit::get_new_args($token,$parstack,
-                                                 $safeeval,'function','label','color','fixed');
+                                                 $safeeval,'function','label','xinitial','xfinal','color','fixed');
     if ($constructtag) { $result=&Apache::edit::rebuild_tag($token); }
   }
   return $result;
@@ -488,7 +694,7 @@ sub start_functionplotrule {
            &Apache::lonxml::get_param('percenterror',$parstack,$safeeval)
           )));
    } elsif ($target eq 'edit') {
-        $result=&Apache::edit::tag_start($target,$token,'Function Plot Evaluation Rule').
+        $result=&Apache::edit::tag_start($target,$token,'Function Plot Graph Rule').
              &Apache::edit::text_arg('Index/Name:','index',
                                      $token,'10').'&nbsp;'.
              &Apache::edit::select_arg(&mt('Function:'),'derivativeorder',
@@ -518,11 +724,17 @@ sub start_functionplotrule {
                                    ['lt','less than'],
                                    ['le','less than or equal']],$token).
              $result.= &Apache::edit::select_or_text_arg('Value:','value',
-                                               [['undef','not defined']],$token,'8').
+                                               [['undef','not defined']],$token,'30').
              &Apache::edit::text_arg('Percent error:','percenterror',
                                      $token,'8').
              &Apache::edit::end_row();
   } elsif ($target eq 'modified') {
+    if (($env{'form.'.&Apache::edit::html_element_name('xinitial')} ne '') && ($env{'form.'.&Apache::edit::html_element_name('xinitiallabel')} eq 'start')) {
+       $env{'form.'.&Apache::edit::html_element_name('xinitiallabel')}='';
+    }
+    if (($env{'form.'.&Apache::edit::html_element_name('xfinal')} ne '') && ($env{'form.'.&Apache::edit::html_element_name('xfinallabel')} eq 'end')) {
+       $env{'form.'.&Apache::edit::html_element_name('xfinallabel')}='';
+    }
     my $constructtag=&Apache::edit::get_new_args($token,$parstack,
                                                  $safeeval,'index','derivativeorder',
                                                            'xinitial','xinitiallabel','xfinal','xfinallabel',
@@ -544,6 +756,206 @@ sub end_functionplotrule {
 
 
 #
+# <functionplotvectorrule ... />
+#
+sub start_functionplotvectorrule {
+   my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
+   my $result='';
+   my $label=&Apache::lonxml::get_param('index',$parstack,$safeeval);
+   $Apache::functionplotresponse::counter++;
+   if ($label=~/\W/) {
+      &Apache::lonxml::warning(&mt('Rule indices should only contain alphanumeric characters.'));
+   }
+   $label=~s/\W//gs;
+   unless ($label) {
+      $label='V'.$Apache::functionplotresponse::counter;
+   } else {
+      $label='V'.$label;
+   }
+   if ($Apache::functionplotresponse::splineorder{$label}) {
+       &Apache::lonxml::error(&mt('Rule indices must be unique.'));
+   }
+
+   if ($target eq 'grade') {
+# Simply remember - in order - for later
+
+      my $id=$Apache::inputtags::response[-1];
+      my $partid=$Apache::inputtags::part;
+      my $internalid = $partid.'_'.$id;
+
+      my $vector=&Apache::lonxml::get_param('vector',$parstack,$safeeval);
+      $vector=~s/\W//gs;
+      $vector=ucfirst($vector);
+
+      my $attachpoint=&Apache::lonxml::get_param('attachpoint',$parstack,$safeeval);
+      $attachpoint=~s/\W//gs;
+      $attachpoint=ucfirst($attachpoint);
+
+      my $notattachpoint=&Apache::lonxml::get_param('notattachpoint',$parstack,$safeeval);
+      $notattachpoint=~s/\W//gs;
+      $notattachpoint=ucfirst($notattachpoint);
+
+      my $tailpoint=&Apache::lonxml::get_param('tailpoint',$parstack,$safeeval);
+      $tailpoint=~s/\W//gs;
+      $tailpoint=ucfirst($tailpoint);
+      my $tippoint=&Apache::lonxml::get_param('tippoint',$parstack,$safeeval);
+      $tippoint=~s/\W//gs;
+      $tippoint=ucfirst($tippoint);
+
+      my $nottailpoint=&Apache::lonxml::get_param('nottailpoint',$parstack,$safeeval);
+      $nottailpoint=~s/\W//gs;
+      $nottailpoint=ucfirst($nottailpoint);
+      my $nottippoint=&Apache::lonxml::get_param('nottippoint',$parstack,$safeeval);
+      $nottippoint=~s/\W//gs;
+      $nottippoint=ucfirst($nottippoint);
+
+      push(@Apache::functionplotresponse::functionplotvectorrules,join(':',(
+           $label,
+           'vector',
+           $internalid,
+           $vector,
+           $attachpoint,
+           $notattachpoint,
+           $tailpoint,
+           $tippoint,
+           $nottailpoint,
+           $nottippoint,
+           &Apache::lonxml::get_param('length',$parstack,$safeeval),
+           &Apache::lonxml::get_param('angle',$parstack,$safeeval),
+           &Apache::lonxml::get_param('lengthpercenterror',$parstack,$safeeval),
+           &Apache::lonxml::get_param('anglepercenterror',$parstack,$safeeval),
+          )));
+   } elsif ($target eq 'edit') {
+        $result=&Apache::edit::tag_start($target,$token,'Function Plot Vector Rule').
+             &Apache::edit::text_arg('Index/Name:','index',
+                                     $token,'10').'&nbsp;'.
+             &Apache::edit::text_arg('Vector:','vector',
+                                      $token,'16').'<br />'.
+             &Apache::edit::text_arg('Attached to object:','attachpoint',
+                                      $token,'16').
+             &Apache::edit::text_arg('Not attached to object:','notattachpoint',
+                                      $token,'16').'<br />'.
+             &Apache::edit::text_arg('Tail attached to object:','tailpoint',
+                                      $token,'16').
+             &Apache::edit::text_arg('Tip attached to object:','tippoint',
+                                      $token,'16').
+             &Apache::edit::text_arg('Tail not attached to object:','nottailpoint',
+                                      $token,'16').
+             &Apache::edit::text_arg('Tip not attached to object:','nottippoint',
+                                      $token,'16').'<br />'.
+             &Apache::edit::text_arg('Length:','length',
+                                     $token,'16').
+             &Apache::edit::text_arg('Angle:','angle',
+                                     $token,'16').
+             &Apache::edit::text_arg('Percent error length:','lengthpercenterror',
+                                     $token,'8').
+             &Apache::edit::text_arg('Percent error angle:','anglepercenterror',
+                                     $token,'8').
+             &Apache::edit::end_row();
+  } elsif ($target eq 'modified') {
+    $env{'form.'.&Apache::edit::html_element_name('vector')}=ucfirst($env{'form.'.&Apache::edit::html_element_name('vector')});
+    $env{'form.'.&Apache::edit::html_element_name('attachpoint')}=ucfirst($env{'form.'.&Apache::edit::html_element_name('attachpoint')});
+    $env{'form.'.&Apache::edit::html_element_name('notattachpoint')}=ucfirst($env{'form.'.&Apache::edit::html_element_name('notattachpoint')});
+    $env{'form.'.&Apache::edit::html_element_name('tailpoint')}=ucfirst($env{'form.'.&Apache::edit::html_element_name('tailpoint')});
+    $env{'form.'.&Apache::edit::html_element_name('tippoint')}=ucfirst($env{'form.'.&Apache::edit::html_element_name('tippoint')});
+    $env{'form.'.&Apache::edit::html_element_name('nottailpoint')}=ucfirst($env{'form.'.&Apache::edit::html_element_name('nottailpoint')});
+    $env{'form.'.&Apache::edit::html_element_name('nottippoint')}=ucfirst($env{'form.'.&Apache::edit::html_element_name('nottippoint')});
+    my $constructtag=&Apache::edit::get_new_args($token,$parstack,
+                                                 $safeeval,'index','vector','attachpoint','notattachpoint',
+                                                           'tailpoint','tippoint','nottailpoint','nottipoint',
+                                                           'length','angle',
+                                                           'lengthpercenterror','anglepercenterror');
+    if ($constructtag) { $result=&Apache::edit::rebuild_tag($token); }
+   }
+   return $result;
+}
+
+sub end_functionplotvectorrule {
+   my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
+   my $result='';
+   if ($target eq 'edit') {
+       $result=&Apache::edit::end_table();
+   }
+   return $result;
+}
+
+#
+# <functionplotvectorsumrule ... />
+#
+sub start_functionplotvectorsumrule {
+   my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
+   my $result='';
+   my $label=&Apache::lonxml::get_param('index',$parstack,$safeeval);
+   $Apache::functionplotresponse::counter++;
+   if ($label=~/\W/) {
+      &Apache::lonxml::warning(&mt('Rule indices should only contain alphanumeric characters.'));
+   }
+   $label=~s/\W//gs;
+   unless ($label) {
+      $label='V'.$Apache::functionplotresponse::counter;
+   } else {
+      $label='V'.$label;
+   }
+   if ($Apache::functionplotresponse::splineorder{$label}) {
+       &Apache::lonxml::error(&mt('Rule indices must be unique.'));
+   }
+   if ($target eq 'grade') {
+# Simply remember - in order - for later
+      my $id=$Apache::inputtags::response[-1];
+      my $partid=$Apache::inputtags::part;
+      my $internalid = $partid.'_'.$id;
+      my $object=&Apache::lonxml::get_param('object',$parstack,$safeeval);
+      $object=~s/\W//gs;
+      $object=ucfirst($object);
+      push(@Apache::functionplotresponse::functionplotvectorrules,join(':',(
+           $label,
+           'sum',
+           $internalid,
+           $object,
+           &Apache::lonxml::get_param('length',$parstack,$safeeval),
+           &Apache::lonxml::get_param('angle',$parstack,$safeeval),
+           &Apache::lonxml::get_param('lengthpercenterror',$parstack,$safeeval),
+           &Apache::lonxml::get_param('lengthabserror',$parstack,$safeeval),
+           &Apache::lonxml::get_param('anglepercenterror',$parstack,$safeeval),
+          )));
+   } elsif ($target eq 'edit') {
+        $result=&Apache::edit::tag_start($target,$token,'Function Plot Vector Sum Rule').
+             &Apache::edit::text_arg('Index/Name:','index',
+                                     $token,'10').'&nbsp;'.
+             &Apache::edit::text_arg('Vectors attached to object:','object',
+                                      $token,'16').'<br />'.
+             &Apache::edit::text_arg('Sum vector length:','length',
+                                     $token,'16').
+             &Apache::edit::text_arg('Sum vector angle:','angle',
+                                     $token,'16').
+             &Apache::edit::text_arg('Percent error length:','lengthpercenterror',
+                                     $token,'8').
+             &Apache::edit::text_arg('Absolute error length:','lengthabserror',
+                                     $token,'8').
+             &Apache::edit::text_arg('Percent error angle:','anglepercenterror',
+                                     $token,'8').
+             &Apache::edit::end_row();
+  } elsif ($target eq 'modified') {
+    $env{'form.'.&Apache::edit::html_element_name('object')}=ucfirst($env{'form.'.&Apache::edit::html_element_name('object')});
+    my $constructtag=&Apache::edit::get_new_args($token,$parstack,
+                                                 $safeeval,'index','object',
+                                                           'length','angle',
+                                                           'lengthpercenterror','lengthabserror','anglepercenterror');
+    if ($constructtag) { $result=&Apache::edit::rebuild_tag($token); }
+   }
+   return $result;
+}
+
+sub end_functionplotvectorsumrule {
+   my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
+   my $result='';
+   if ($target eq 'edit') {
+       $result=&Apache::edit::end_table();
+   }
+   return $result;
+}
+
+#
 # <spline index="..." order="1,2,3,4" initx="..." inity="..." scalex="..." scaley="..." />
 #
 # Unfortunately, GeoGebra seems to want all splines after everything else, so we need to store them
@@ -700,7 +1112,7 @@ sub array_index {
 #
 
 sub populate_arrays {
-    my ($id,$xmin,$xmax)=@_;
+    my ($id,$xmin,$xmax,$ymin,$ymax)=@_;
     for (my $i=0; $i<=400; $i++) {
        $Apache::functionplotresponse::actualxval[$i]=undef;
        $Apache::functionplotresponse::func[$i]=undef;
@@ -728,12 +1140,19 @@ sub populate_arrays {
                 my $xi=&array_index($xmin,$xmax,$xreal);
                 if ($xi<$xiold) { return 'no_func'; }
                 if (($xi>$xiold) && ($xi>=0) && ($xi<=400)) {
-                   if (defined($Apache::functionplotresponse::func[$xi])) { return 'no_func'; }
                    $xiold=$xi;
                    $Apache::functionplotresponse::actualxval[$xi]=$xreal;
 # Function value
                    my $funcval=&cubic_hermite($t,@yparms);
+
+# Do we already have a value for this point, and is it different from the new one?
+                   if ((defined($Apache::functionplotresponse::func[$xi])) &&
+                       (abs($Apache::functionplotresponse::func[$xi]-$funcval)>($ymax-$ymin)/100.)) { 
+                       return 'no_func'; 
+                   }
+# Okay, remember the new point
                    $Apache::functionplotresponse::func[$xi]=$funcval;
+
                    if (defined($funcval)) {
                       if ($xi<$Apache::functionplotresponse::functionplotrulelabels{'start'}) {
                          $Apache::functionplotresponse::functionplotrulelabels{'start'}=$xi;
@@ -777,6 +1196,7 @@ sub start_functionplotresponse {
   $Apache::functionplotresponse::counter=0;
 # Remember rules
   undef @Apache::functionplotresponse::functionplotrules;
+  undef @Apache::functionplotresponse::functionplotvectorrules;
 # Remember failed rules
   if ($target eq 'grade') {
      undef @Apache::functionplotresponse::failedrules;
@@ -803,7 +1223,8 @@ sub start_functionplotresponse {
        .'<tr><td><span class="LC_nobreak">'.&mt('Function Plot Question').'</span></td>'
        .'<td><span class="LC_nobreak">'.&mt('Delete?').' '
        .&Apache::edit::deletelist($target,$token).'&nbsp;&nbsp;&nbsp;'
-       .&Apache::edit::insertlist($target,$token)
+       .&Apache::edit::insertlist($target,$token).'&nbsp;&nbsp;&nbsp;'
+       .&Apache::loncommon::help_open_topic('Function_Plot_Response_Question','Function Plot Responses')
        .'</span></td>'
        ."<td>&nbsp;"
        .&Apache::edit::end_row()
@@ -826,12 +1247,14 @@ sub start_functionplotresponse {
              &Apache::edit::select_arg('y-axis visible:','yaxisvisible',
                                   ['yes','no'],$token).'<br />'.
              &Apache::edit::select_arg('Grid visible:','gridvisible',
-                                  ['yes','no'],$token).
+                                  ['yes','no'],$token).'<br />'.
+             &Apache::edit::text_arg('Background plot(s) for answer (function(x):xmin:xmax,function(x):xmin:xmax,x1:y1:sx1:sy1:x2:y2:sx2:sy2,...):',
+                                         'answerdisplay',$token,'50').
              &Apache::edit::end_row().&Apache::edit::start_spanning_row();
   } elsif ($target eq 'modified') {
     my $constructtag=&Apache::edit::get_new_args($token,$parstack,
                                                  $safeeval,'xlabel','xmin','xmax','ylabel','ymin','ymax',
-                                                           'xaxisvisible','yaxisvisible','gridvisible');
+                                                           'xaxisvisible','yaxisvisible','gridvisible','answerdisplay');
     if ($constructtag) { $result = &Apache::edit::rebuild_tag($token); }
 
   } elsif ($target eq 'meta') {
@@ -911,6 +1334,7 @@ sub compare_rel {
 
 sub addlog {
    my ($text)=@_;
+   $text=~s/\'/\\\'/g;
    $Apache::functionplotresponse::ruleslog.=$text.'<br />';
 }
 
@@ -918,15 +1342,115 @@ sub actualval {
    my ($i,$xmin,$xmax)=@_;
    return $xmin+$i/400.*($xmax-$xmin);
 }
+
+sub fpr_val {
+   my ($arg)=@_;
+   return &actualval($Apache::functionplotresponse::functionplotrulelabels{$arg},
+                     $Apache::functionplotresponse::fpr_xmin,
+                     $Apache::functionplotresponse::fpr_xmax);
+}
+
+sub fpr_f {
+   my ($arg)=@_;
+   return $Apache::functionplotresponse::func[&array_index($Apache::functionplotresponse::fpr_xmin,
+                                                           $Apache::functionplotresponse::fpr_xmax,
+                                                           $arg)];
+}
+
+sub fpr_dfdx {
+   my ($arg)=@_;
+   return $Apache::functionplotresponse::dfuncdx[&array_index($Apache::functionplotresponse::fpr_xmin,
+                                                              $Apache::functionplotresponse::fpr_xmax,
+                                                              $arg)];
+}
+
+sub fpr_d2fdx2 {
+   my ($arg)=@_;
+   return $Apache::functionplotresponse::d2funcdx2[&array_index($Apache::functionplotresponse::fpr_xmin,
+                                                                $Apache::functionplotresponse::fpr_xmax,
+                                                                $arg)];
+}
+
+
+sub vectorcoords {
+   my ($id,$label)=@_;
+   return ($env{'form.HWVAL_'.$id.'_'.$label.'Start_x'},
+           $env{'form.HWVAL_'.$id.'_'.$label.'End_x'},
+           $env{'form.HWVAL_'.$id.'_'.$label.'Start_y'},
+           $env{'form.HWVAL_'.$id.'_'.$label.'End_y'});
+}
+
+sub objectcoords {
+   my ($id,$label)=@_;
+   return ($env{'form.HWVAL_'.$id.'_'.$label.'_x'},
+           $env{'form.HWVAL_'.$id.'_'.$label.'_y'});
+}
+ 
+sub vectorangle {
+   my ($x,$y)=@_;
+}
+
+sub vectorlength {
+   my ($x,$y)=@_;
+   return sqrt($x*$x+$y*$y);
+}
+
+
+#
+# Evaluate a functionplotvectorrule
+#
+
+sub functionplotvectorrulecheck {
+   my ($rule,$xmin,$xmax,$ymin,$ymax,$safeeval)=@_;
+   my ($label,$type)=split(/\:/,$rule);
+   if ($type eq 'vector') {
+      return &vectorcheck($rule,$xmin,$xmax,$ymin,$ymax,$safeeval);
+   } elsif ($type eq 'sum') {
+      return &sumcheck($rule,$xmin,$xmax,$ymin,$ymax,$safeeval);
+   }
+}
+
+sub vectorcheck {
+   my ($rule,$xmin,$xmax,$ymin,$ymax,$safeeval)=@_;
+   my ($label,$type,$id,$vector,
+       $attachpoint,$notattachpoint,
+       $tailpoint,$tippoint,$nottailpoint,$nottippoint,
+       $length,$angle,$lengthpercenterror,$anglepercenterror)=split(/\:/,$rule);
+}
+
+sub sumcheck {
+   my ($rule,$xmin,$xmax,$ymin,$ymax,$safeeval)=@_;
+   my ($label,$type,$id,$object,$length,$angle,$lengthpercenterror,$lengthabserror,$anglepercenterror)=split(/\:/,$rule);
+}
+
+#
+# Evaluate a functionplotrule
+#
  
 sub functionplotrulecheck {
-   my ($rule,$xmin,$xmax,$ymin,$ymax)=@_;
+   my ($rule,$xmin,$xmax,$ymin,$ymax,$safeeval)=@_;
 
    my ($label,$derivative,$xinitial,$xinitiallabel,$xfinal,$xfinallabel,$minimumlength,$maximumlength,$relationship,$value,$percent)
       =split(/\:/,$rule);
    $percent=($percent>0?$percent:5);
    &addlog("=================");
    &addlog("Rule $label for ".($derivative<0?'integral':('function itself','first derivative','second derivative')[$derivative])." $relationship $value");
+#
+# Evaluate the value
+#
+   if ($value=~/\D/) {
+      $Apache::functionplotresponse::fpr_xmin=$xmin;
+      $Apache::functionplotresponse::fpr_xmax=$xmax;
+      $value=&Apache::run::run($value,$safeeval);
+      &addlog("Value evaluated to $value");
+   }
+
+#
+# Minimum and maximum lengths of the interval
+#
+   if ((defined($minimumlength)) || (defined($maximumlength))) {
+      &addlog("Minimumlength $minimumlength Maximumlength $maximumlength");
+   }
    my $li=0;
    my $lh=400;
 
@@ -1021,38 +1545,59 @@ sub functionplotrulecheck {
            &addlog("Actual value ".(defined($val)?$val:'undef').", expected $value, tolerance $tol");
            &addlog("Condition not fulfilled at x=".&actualval($i,$xmin,$xmax)." (".$Apache::functionplotresponse::actualxval[$i]."; index $i)");
            if (($findupper) && ($i>$li)) {
-# check for minimum and maximum lengths
-              my $length=&actualval($i,$xmin,$xmax)-&actualval($li,$xmin,$xmax);
-              if ($minimumlength) {
-                 if ($length<$minimumlength) {
-                    &addlog("Rule $label failed, actual length $length, minimum length $minimumlength");
-                    return 0;
-                 }
-              }
-              if ($maximumlength) {
-                 if ($length>$maximumlength) {
-                    &addlog("Rule $label failed, actual length $length, maximum length $maximumlength");
-                    return 0;
-                 }
-              }
+# Check lengths
+              unless (&checklength($i,$li,$minimumlength,$maximumlength,$xmin,$xmax,$label)) { return 0; }
+# Successfully found a new label, set it
               $Apache::functionplotresponse::functionplotrulelabels{$xfinallabel}=$i;
               &addlog("Rule $label passed, setting label $xfinallabel");
               return 1;
            } else {
               &addlog("Rule $label failed.");
-              my $hintlabel=$label;
-              $hintlabel=~s/^R//;
-              push(@Apache::functionplotresponse::failedrules,$hintlabel);
-              &addlog("Set hint condition $hintlabel");
+              &setfailed($label);
               return 0; 
            }
         }
      }
    }
+# Corner case where this makes sense: using start or stop as defined labels
+   unless (&checklength($lh,$li,$minimumlength,$maximumlength,$xmin,$xmax,$label)) { return 0; }
    &addlog("Rule $label passed.");
    return 1;
 }
 
+#
+# check for minimum and maximum lengths
+#
+
+sub checklength {
+    my ($i,$li,$minimumlength,$maximumlength,$xmin,$xmax,$label)=@_;
+    unless (($minimumlength) || ($maximumlength)) { return 1; }
+    my $length=&actualval($i,$xmin,$xmax)-&actualval($li,$xmin,$xmax);
+    if ($minimumlength) {
+       if ($length<$minimumlength) {
+          &addlog("Rule $label failed, actual length $length, minimum length $minimumlength");
+          &setfailed($label);
+          return 0;
+       }
+    }
+    if ($maximumlength) {
+       if ($length>$maximumlength) {
+          &addlog("Rule $label failed, actual length $length, maximum length $maximumlength");
+          &setfailed($label);
+          return 0;
+       }
+    }
+    return 1;
+}
+
+sub setfailed {
+   my ($label)=@_;
+   my $hintlabel=$label;
+   $hintlabel=~s/^R//;
+   push(@Apache::functionplotresponse::failedrules,$hintlabel);
+   &addlog("Set hint condition $hintlabel");
+}
+
 sub start_functionplotruleset {
    my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
    if ($target eq 'edit') {
@@ -1060,7 +1605,8 @@ sub start_functionplotruleset {
         '<tr><td><span class="LC_nobreak">'.&mt('Function Plot Rule Set').'</span></td>'
        .'<td><span class="LC_nobreak">'.&mt('Delete?').' '
        .&Apache::edit::deletelist($target,$token).'&nbsp;&nbsp;&nbsp;'.
-        &Apache::edit::insertlist($target,$token)
+        &Apache::edit::insertlist($target,$token).'&nbsp;&nbsp;&nbsp;'
+       .&Apache::loncommon::help_open_topic('Function_Plot_Response_Rule_Set','Function Plot Rules')
        .'</span></td>'
        ."<td>&nbsp;"
        .&Apache::edit::end_row()
@@ -1090,7 +1636,7 @@ sub end_functionplotruleset {
         $Apache::functionplotresponse::ruleslog='';
         $Apache::functionplotresponse::functionplotrulelabels{'start'}=400;
         $Apache::functionplotresponse::functionplotrulelabels{'end'}=0;
-        if (&populate_arrays($internalid,$xmin,$xmax) eq 'no_func') {
+        if (&populate_arrays($internalid,$xmin,$xmax,$ymin,$ymax) eq 'no_func') {
            $ad='NOT_FUNCTION';
         } else {
            &addlog("Start of function ".&actualval($Apache::functionplotresponse::functionplotrulelabels{'start'},$xmin,$xmax)." (index ".
@@ -1100,7 +1646,14 @@ sub end_functionplotruleset {
 
 # We have a function that we can actually grade, go through the spline rules.
            foreach my $rule (@Apache::functionplotresponse::functionplotrules) {
-              unless (&functionplotrulecheck($rule,$xmin,$xmax,$ymin,$ymax)) {
+              unless (&functionplotrulecheck($rule,$xmin,$xmax,$ymin,$ymax,$safeeval)) {
+                 $ad='INCORRECT';
+                 last;
+              }
+           }
+# And now go through the vector rules
+           foreach my $rule (@Apache::functionplotresponse::functionplotvectorrules) {
+              unless (&functionplotvectorrulecheck($rule,$xmin,$xmax,$ymin,$ymax,$safeeval)) {
                  $ad='INCORRECT';
                  last;
               }
@@ -1162,10 +1715,34 @@ sub end_functionplotelements {
   if ($target eq 'edit' ) {
      $result=&Apache::edit::end_table();
   } elsif ($target eq 'web') {
-# Now is the time to render all of the stored splines
      my ($xmin,$xmax,$ymin,$ymax)=&boundaries($parstack,$safeeval,-2);
+
+# Are we in show answer mode?
+     my $showanswer=&Apache::response::show_answer();
+     if ($showanswer) {
+# Render answerdisplay
+        my $answerdisplay=&Apache::lonxml::get_param('answerdisplay',$parstack,$safeeval,-2);
+        if ($answerdisplay=~/\S/s) {
+           foreach my $plot (split(/\s*\,\s*/,$answerdisplay)) {
+              my @components=split(/\s*\:\s*/,$plot);
+              if ($#components<3) {
+# Just a simple plot
+                 my ($func,$xl,$xh)=@components;
+                 if ((!defined($xl)) || ($xl eq '')) { $xl=$xmin; }
+                 if ((!defined($xh)) || ($xh eq '')) { $xh=$xmax; }
+                 $result.=&plot_script($internalid,$func,1,'','00aa00',$xl,$xh,6);
+              } else {
+# This is a spline
+                 $result.=&answer_spline_script($internalid,@components);
+              }
+           }
+        }
+     }
+     my $fixed=0;
+     if (($showanswer) || (&Apache::response::check_status()>=2)) { $fixed=1; }
+# Now is the time to render all of the stored splines
      foreach my $label (keys(%Apache::functionplotresponse::splineorder)) {
-        $result.=&generate_spline($internalid,$label,$xmin,$xmax,$ymin,$ymax);
+        $result.=&generate_spline($internalid,$label,$xmin,$xmax,$ymin,$ymax,$fixed);
      }
 # close the init script
      $result.=&end_init_script();
@@ -1221,7 +1798,8 @@ sub start_functionplotelements {
         '<tr><td><span class="LC_nobreak">'.&mt('Function Plot Elements').'</span></td>'
        .'<td><span class="LC_nobreak">'.&mt('Delete?').' '
        .&Apache::edit::deletelist($target,$token).'&nbsp;&nbsp;&nbsp;'.
-        &Apache::edit::insertlist($target,$token)
+        &Apache::edit::insertlist($target,$token).'&nbsp;&nbsp;&nbsp;'
+       .&Apache::loncommon::help_open_topic('Function_Plot_Response_Elements','Function Plot Elements')
        .'</span></td>'
        ."<td>&nbsp;"
        .&Apache::edit::end_row()