File:  [LON-CAPA] / loncom / xml / scripttag.pm
Revision 1.173: download - view: text, annotated - select for diffs
Mon Jan 19 15:36:16 2015 UTC (9 years, 3 months ago) by goltermann
Branches: MAIN
CVS tags: HEAD
authoring space overhaul
this update tries to improve the user experience of the authoring space.

added codemirror for xml editor and script tags in colorful editor
added possibility to deactivate codemirror in author settings
added dropdown menu to insert problem templates into xml editor (thanks to tobias reinhardt)
added feature of saving current scrollposition on save when editing problems
added possibility to fold blocks in colorful editor, this state will be saved and restored
added shortcuts to create empty problems, html files and directories

and other smaller features and bugfixes

# The LearningOnline Network with CAPA
# <script> definiton
#
# $Id: scripttag.pm,v 1.173 2015/01/19 15:36:16 goltermann Exp $
#
# Copyright Michigan State University Board of Trustees
#
# This file is part of the LearningOnline Network with CAPA (LON-CAPA).
#
# LON-CAPA is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# LON-CAPA is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with LON-CAPA; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#
# /home/httpd/html/adm/gpl.txt
#
# http://www.lon-capa.org/
#

package Apache::scripttag;

use strict;
use Apache::lonnet;
use Apache::lonlocal;
use Apache::lonxml();
use Apache::londefdef();
use Apache::style();

#Globals
# this used to pass around the standard callsub arguments to a tag func
# so xmlparse can reenter the inner_xmlparse loop.

@Apache::scripttag::parser_env = ();
BEGIN {
  &Apache::lonxml::register('Apache::scripttag',
			    ('script','scriptlib','parserlib','import',
			     'window','windowlink','togglebox','display','storetc','physnet',
			     'standalone','comment','num','parse','algebra',
			     'LONCAPA_INTERNAL_TURN_STYLE_ON',
			     'LONCAPA_INTERNAL_TURN_STYLE_OFF'));
}

sub start_LONCAPA_INTERNAL_TURN_STYLE_ON {
    $Apache::lonxml::usestyle=1;
    $Apache::lonxml::style_values='';
    return ('','no');
}

sub end_LONCAPA_INTERNAL_TURN_STYLE_ON {
    my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_;
    my $end=&Apache::lonxml::get_param('end',$parstack,$safeeval);
    if (defined($end)) {
	&Apache::lonxml::end_tag($tagstack,$parstack,$token);
    }
    return ('','no');
}

sub start_LONCAPA_INTERNAL_TURN_STYLE_OFF {
    my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_;
    $Apache::lonxml::usestyle=0;
    my $end=&Apache::lonxml::get_param('end',$parstack,$safeeval);
    if (!$end) {
	$Apache::lonxml::style_values=$$parstack[-1];
	$Apache::lonxml::style_end_values=$$parstack[-1];
    } else {
	$Apache::lonxml::style_values=$Apache::lonxml::style_end_values;
	$Apache::lonxml::style_end_values='';
    }
    return ('','no');
}

sub end_LONCAPA_INTERNAL_TURN_STYLE_OFF {
    return ('','no');
}

sub start_script {
  my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_;
  @Apache::scripttag::parser_env = @_;
  my $result='';
  my $type= &Apache::lonxml::get_param('type',$parstack,$safeeval);
  &Apache::lonxml::debug("found type of $type");
  if ($type eq "loncapa/perl") {
    if ( $target eq "modified" ) {
	$result=$token->[4].&Apache::edit::modifiedfield('/script',$parser);
    } elsif ( $target eq 'web' || $target eq 'tex' ||
	      $target eq 'grade' || $target eq 'webgrade' ||
	      $target eq 'answer' || $target eq 'analyze' ) {
	my $bodytext=&Apache::lonxml::get_all_text_unbalanced("/script",$parser);
	if (!$Apache::lonxml::default_homework_loaded) {
	    &Apache::lonxml::default_homework_load($safeeval);
	}
	&Apache::run::run($bodytext,$safeeval);
	if (($target eq 'answer') &&
	    ($env{'form.answer_output_mode'} ne 'tex') &&
	    ($Apache::lonhomework::viewgrades == 'F')) {
	    $Apache::lonxml::evaluate--;
	    my (undef,undef,$udom,$uname)=&Apache::lonnet::whichuser();
	    $uname =~s/\W//g;
	    $udom  =~s/\W//g;
	    my $function_name = 
		join('_','LONCAPA_scriptvars',$uname,$udom,
		     $env{'form.counter'},$Apache::lonxml::curdepth);
            &Apache::lonxml::add_script_result(
	             &Apache::loncommon::modal_adhoc_window($function_name,500,500,
                            '<pre style="background-color:#ffffff;">'.
                            &Apache::run::dump($target,$safeeval).'</pre>',
                            &mt('Script Vars'))."<br />");
	}
    } elsif ($target eq "edit" ) {
      #&Apache::run::run($bodytext,$safeeval);
      #$result="<br /> &lt;$token->[1]&gt; output: <br />$bodytext<br />Source:<br />";
    	my $bodytext=&Apache::lonxml::get_all_text_unbalanced("/script",$parser);
    	$result=&Apache::edit::tag_start($target,$token,'Script');

        my $depth = $Apache::lonxml::curdepth;
        $result.='<span id="LC_edit_problem_codemirror">';
        unless ($env{'environment.nocodemirror'}) {
            # only show button if codemirror activated
            $result.='<input type="button" id="fitsize'.$depth.'" value="'.&mt("Dynamic size").
            '" onclick="autosize(\''.$depth.'\')" />';
        }
        $result.=&Apache::edit::editfield($token->[1],$bodytext,'',80,4).'</span>';

        unless ($env{'environment.nocodemirror'}) {
            $result.='<script type="text/javascript">
                var cm'.$depth.' = CodeMirror.fromTextArea(document.getElementById("homework_edit_'.$depth.'"),
                {
                    mode: "perl",
                    lineWrapping: true,
                    lineNumbers: true,
                    tabSize: 4,
                    indentUnit: 4,
                    autoCloseBrackets: true,
                    styleActiveLine: true,
                    
                    extraKeys: {
                        "Tab": "indentMore",
                        "Shift-Tab": "indentLess"
                    }
                });
                if(sessionStorage.getItem("autosized_'.$depth.'") != null) {
                    document.getElementById("fitsize'.$depth.'").value = "'.&mt("Fixed size").'";
                    cm'.$depth.'.setSize("","auto");
                }
            </script>';
        }
                

    } elsif ($target eq 'meta') {
	my $bodytext=&Apache::lonxml::get_all_text_unbalanced("/script",$parser);
    }
  } else {
      my $bodytext=&Apache::lonxml::get_all_text_unbalanced("/script",$parser);
      if ($target ne "meta" && $target ne 'tex' && $target ne 'answer') {
	  $result = $token->[4];
	  $result.=$bodytext;
          my $src=&Apache::lonxml::get_param('src',$parstack,$safeeval,undef,1);
          my $url=&Apache::lonnet::hreflocation('',$env{'request.filename'});
          my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
          my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
          if ($src ne '') {
              if ($src !~ m{^(/|https?://)}) {
                  my $cleanhref = &Apache::londefdef::clean_docs_httpref($src,$url,$cdom,$cnum);
                  if ($cleanhref) {
                      &Apache::lonxml::extlink($cleanhref);
                  }
              }
          } elsif (($type eq 'text/javascript') && ($bodytext ne '')) {
              if ($url =~ m{^\Q/uploaded/$cdom/$cnum/\E(docs|supplemental)/}) {
                  if ($bodytext =~ m{\.addMediaSrc\((["'])((?!\1).)+\1\);}) {
                      my $quote = $1;
                      if ($bodytext =~ m{\Q.addMediaSrc($quote\E([^$quote]+)\Q$quote)\E}) {
                          my $fname = $1;
                          my $cleanhref =
                              &Apache::londefdef::clean_docs_httpref($fname,$url,$cdom,$cnum);
                          if ($cleanhref) {
                              &Apache::lonxml::extlink($cleanhref);
                          }
                      }
                  }
                  if ($bodytext =~ m{\.set\w+(Src|Swf)\(["']}i) {
                      my @srcs = split(/\.set/,$bodytext);
                      if (scalar(@srcs) > 1) {
                          foreach my $item (@srcs) {
                              if ($item =~ m{^(FlashPlayerSwf|MediaSrc|XMPSrc|ConfigurationSrc|PosterImageSrc)\((['"])(?:(?!\2).)+\2\)}is) {
                                  my $srctype = $1;
                                  my $quote = $2;
                                  my ($fname) = ($item =~ m{^\Q$srctype($quote\E([^$quote]+)\Q$quote)\E}); 
                                  my $cleanhref =
                                      &Apache::londefdef::clean_docs_httpref($fname,$url,$cdom,$cnum);
                                  if ($cleanhref) {
                                      &Apache::lonxml::extlink($cleanhref);
                                      if ($srctype eq 'ConfigurationSrc') {
                                          if ($cleanhref =~ m{^(.+/)configuration_express\.xml$}) {
#
# Camtasia 8.1: express_show/spritesheet.png needed, and included in zip archive.
# Not referenced directly in <main>.html or <main>_player.html files,
# so call lonxml::extlink() here to include httpref for the uploaded file.
# (where <main> is name user gave to file/archive).
#

                                              my $spritesheet = $1.'express_show/spritesheet.png';
                                              if (&Apache::lonnet::repcopy_userfile($spritesheet) eq 'ok') {
                                                  &Apache::lonxml::extlink($spritesheet);
                                              }
                                          }
#
# Camtasia 8.4: express_show/spritesheet.min.css needed, and included in zip archive.
# Not referenced directly in <main>.html or <main>_player.html files,
# so call lonxml::extlink() here to include httpref for the uploaded file.
# (where <main> is name user gave to file/archive).
#
                                          my $spritesheet_css = $1.'express_show/spritesheet.min.css';
                                          if (&Apache::lonnet::repcopy_userfile($spritesheet_css) eq 'ok') {
                                              &Apache::lonxml::extlink($spritesheet_css);
                                          }
                                      } elsif ($srctype eq 'PosterImageSrc') {
                                          if ($fname =~ m{^(.+)_First_Frame\.png$}) {
                                              my $prefix = $1;
                                              my ($path) = ($cleanhref =~ m{^(.+/)\Q$fname\E});
#
# Camtasia 8.1: <main>_Thumbnails.png needed, and included in zip archive.
# Not referenced directly in <main>.html or <main>_player.html files,
# so call lonxml::extlink() here to include httpref for the uploaded file
# (where <main> is name user gave to file/archive).
#
                                              my $thumbnail = $path.$prefix.'_Thumbnails.png';
                                              if (&Apache::lonnet::repcopy_userfile($thumbnail) eq 'ok') {
                                                  &Apache::lonxml::extlink($thumbnail);
                                              }
                                          }
                                      }
                                  }
                              }
                          }
                      }
                  }
                  if ($bodytext =~ /\(document,\s*(['"])script\1,\s*\[([^\]]+)\]\);/s) {
                      my $scriptslist = $2;
                      my @srcs = split(/\s*,\s*/,$scriptslist);
                      foreach my $src (@srcs) {
                          if ($src =~ /(["'])(?:(?!\1).)+\.js\1/) {
                              my $quote = $1;
                              my ($fname) = ($src =~ m/\Q$quote\E([^$quote]+)\Q$quote\E/);
                              my $cleanhref =
                                  &Apache::londefdef::clean_docs_httpref($fname,$url,$cdom,$cnum);
                              if ($cleanhref) {
                                  &Apache::lonxml::extlink($cleanhref);
                              }
                          }
                      }
                  }
                  if ($bodytext =~ m{loadScript\(\s*(['"])((?:(?!\1).)+\.js)\1,\s*function}is) {
                      my $fname = $2;
                      if ($fname) {
                          my $cleanhref =
                              &Apache::londefdef::clean_docs_httpref($fname,$url,$cdom,$cnum);
                          if ($cleanhref) {
                              &Apache::lonxml::extlink($cleanhref);
                          }
                      }
                  }
              }
          }
      }
  }
  return $result;
}

sub end_script {
  my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_;
  if ( $target eq "meta" ) { return ''; } 
  my $type = &Apache::lonxml::get_param('type',$parstack,$safeeval);
  my $result='';
  #other script blocks need to survive
  if ($type ne "loncapa/perl" && $target ne 'tex') {
    return $token->[2];
  } elsif ($target eq 'edit' ) {
    return &Apache::edit::end_table();
  } elsif ($target eq 'answer') {
    $Apache::lonxml::evaluate++;
  }
  return '';
}

sub start_display {
  my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_;
  @Apache::scripttag::parser_env = @_;
  my $result;

  if ( $target eq "modified" ) {
      $result=$token->[4].&Apache::edit::modifiedfield("/display",$parser);
  } elsif ( $target eq 'web' || $target eq 'tex' ||
	    $target eq 'grade' || $target eq 'webgrade' ||
	    $target eq 'answer' || $target eq 'analyze') {
      my $bodytext=&Apache::lonxml::get_all_text_unbalanced("/display",$parser);
      if (!$Apache::lonxml::default_homework_loaded) {
	  &Apache::lonxml::default_homework_load($safeeval);
      }
      $result=&Apache::run::run($bodytext,$safeeval);
      if ($target eq 'grade' || $target eq 'answer' ||
	  $target eq 'analyze') {
	  # grade/answer/analyxe should produce no output but if we
	  # are redirecting, the redirecter should know what to do
	  # with the output
	  if (!$Apache::lonxml::redirection) { $result=''; }
      }
      $Apache::lonxml::post_evaluate=0;
  } elsif ($target eq "edit" ) {
    my $bodytext=&Apache::lonxml::get_all_text_unbalanced("/display",$parser);
    #$result = 
    #  "<br /> &lt;$token->[1]&gt; output: <br />$bodytext<br />Source:<br />";
    #$result.=&Apache::edit::editfield($token->[1],$bodytext,'',40,1);
    $result=&Apache::edit::tag_start($target,$token,'Script With Display');
    $result.=&Apache::edit::editfield($token->[1],$bodytext,'',80,1)
  } elsif ($target eq 'meta') {
      my $bodytext=&Apache::lonxml::get_all_text_unbalanced("/display",$parser);
  }
  return $result;
}

sub end_display {
  my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_;
  if ($target eq 'edit' ) { return &Apache::edit::end_table(); }
  return '';
}

sub start_scriptlib {
  my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
  my $bodytext;
  my $result ='';
  my $error='';

  if ($target eq 'web' || $target eq 'tex' || $target eq 'grade' ||
      $target eq 'meta' || $target eq 'edit' || $target eq 'answer' ||
      $target eq 'analyze' || $target eq 'webgrade') {
    $bodytext=$$parser[$#$parser]->get_text("/scriptlib");
    $bodytext=&Apache::run::evaluate($bodytext,$safeeval,
				     $$parstack[$#$parstack]);
    my $location=&Apache::lonnet::filelocation($Apache::lonxml::pwd['-1'],
					       $bodytext);
    my $script=&Apache::lonnet::getfile($location);
    if ($script == -1) {
      if ($target eq 'edit') {
        $error='</tr><tr><td>'.&mt('Errors').'</td><td colspan="2"><b>'.&mt(' Unable to find [_1]','<span class="LC_filename">'.$location.'</span>').'</b></td>'."\n";
      } else {
	&Apache::lonxml::error("<b> Unable to find <i>$location</i> for scriptlib</b>");
	return "";
      }
    }
    &Apache::run::run($script,$safeeval);
    #&Apache::lonxml::debug("ran $bodytext:<br />".&Apache::lonnet::getfile($bodytext)."<br />");
  }
  if ($target eq "edit" ) {
    $result=
      &Apache::edit::tag_start($target,$token,'New Script Functions').
	&Apache::edit::editline($token->[1],$bodytext,'scriptlib',40).
            &Apache::edit::browse(undef,'textnode').
	  $error.'</td></tr>'.
	    &Apache::edit::end_table();
  }
  if ($target eq "modified" ) {
      $result=$token->[4].&Apache::edit::modifiedfield("/scriptlib",$parser);
  }
  return $result;
}

sub end_scriptlib {
  my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
  my @result;
  if ($target eq "edit" ) { $result[1]='no'; }
  return @result;
}

sub start_parserlib {
  my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
  my $bodytext;
  my $result ="";
  my $error='';
  if ($target eq 'web' || $target eq 'tex' || $target eq 'grade' ||
      $target eq 'meta' || $target eq 'edit' || $target eq 'answer' ||
      $target eq 'analyze' || $target eq 'webgrade') {
    $bodytext=$$parser[$#$parser]->get_text("/parserlib");
    $bodytext=&Apache::run::evaluate($bodytext,$safeeval,
				     $$parstack[$#$parstack]);
    my $location=&Apache::lonnet::filelocation($Apache::lonxml::pwd['-1'],
					       $bodytext);
    my $styletext=&Apache::lonnet::getfile($location);
    #&Apache::lonxml::debug("found :$bodytext: in :$location: with :$styletext:");
    if ($styletext == -1) {
      if ($target eq 'edit') {
	$error='</tr><tr><td>Errors</td><td colspan="2"><b> Unable to find <i>'.$location.'</i></b></td>'."\n";
      } else {
	&Apache::lonxml::error("<b> Unable to find <i>$location</i> for parserlib</b>");
	return "";
      }
    }
    %$style = ( %$style , &Apache::style::styleparser($target,$styletext));
  }
  if ($target eq "edit" ) {
    $result=
      &Apache::edit::tag_start($target,$token,'New Tag Definitions').
	&Apache::edit::editline($token->[1],$bodytext,'',40).
	  $error.'</td></tr>'.
	    &Apache::edit::end_table();
  }
  if ($target eq "modified" ) {
      $result=$token->[4].&Apache::edit::modifiedfield("/parserlib",$parser);
  }
  return $result;
}

sub end_parserlib {
  my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
  my @result;
  if ($target eq "edit" ) { $result[1]='no'; }
  return @result;
}

sub start_window {
    my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
    my $result = '';
    if ($target eq 'web' || $target eq 'webgrade') {
	&Apache::lonxml::startredirection;
    } elsif ($target eq 'tex') {
        my $printtext=&Apache::lonxml::get_param('printtext',$parstack,$safeeval);
        if ($printtext=~/\w/) {
# If printtext is given, do not output any intervening information
           &Apache::lonxml::startredirection;
        } else {
           $result = '\unskip\footnote{';
        }
    } elsif ($target eq 'edit') {
	$result.=&Apache::edit::tag_start($target,$token);
	$result.=&Apache::edit::text_arg('Text of Link:','linktext',$token,70);
	$result.=&Apache::edit::text_arg('Height:','height',$token,5);
	$result.=&Apache::edit::text_arg('Width:','width',$token,5);
        $result.=&Apache::edit::text_arg('Printed text (optional):','printtext',$token,20);
	$result .=&Apache::edit::end_row().&Apache::edit::start_spanning_row();
    } elsif ($target eq 'modified') {
	my $constructtag=&Apache::edit::get_new_args($token,$parstack,
						     $safeeval,'linktext',
						     'width','height');
	if ($constructtag) { $result=&Apache::edit::rebuild_tag($token); }
    }
    return $result;  
}

sub end_window {
  my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
  my $result;
  if ($target eq 'web' || $target eq 'webgrade') {
    my $output=&Apache::lonxml::endredirection;
    my $linktext= &Apache::lonxml::get_param('linktext',$parstack,$safeeval);
    if (!$linktext) { $linktext='<sup>*</sup>'; }
    my $width= &Apache::lonxml::get_param('width',$parstack,$safeeval);
    if (!$width) { $width='500'; }
    my $height= &Apache::lonxml::get_param('height',$parstack,$safeeval);
    if (!$height) { $height='200'; }
    $result=&Apache::loncommon::modal_adhoc_window
           ("LONCAPA_newwindow_$Apache::lonxml::curdepth",$width,$height,$output,$linktext);
  } elsif ($target eq 'tex') {
      my $printtext=&Apache::lonxml::get_param('printtext',$parstack,$safeeval);
      if ($printtext=~/\w/) {
# If a "printtext" is given, proceed to retrieve all intervening information and trash it
         my $output=&Apache::lonxml::endredirection;
# Use printtext instead
         $result=$printtext;
      } else {
         $result='}';
      }
  } else {
      $result = '';
  }
  return $result; 
}


sub start_windowlink {
    my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
    my $result = '';
    if ($target eq 'web' || $target eq 'webgrade') {
        &Apache::lonxml::startredirection;
    } elsif ($target eq 'edit') {
        $result.=&Apache::edit::tag_start($target,$token);
        $result.=&Apache::edit::text_arg('Link:','href',$token,70);
        $result.=&Apache::edit::text_arg('Height:','height',$token,5);
        $result.=&Apache::edit::text_arg('Width:','width',$token,5);
        $result .=&Apache::edit::end_row().&Apache::edit::start_spanning_row();
    } elsif ($target eq 'modified') {
        my $constructtag=&Apache::edit::get_new_args($token,$parstack,
                                                     $safeeval,'href',
                                                     'width','height');
        if ($constructtag) { $result=&Apache::edit::rebuild_tag($token); }
    }
    return $result;
}

sub end_windowlink {
  my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
  my $result;
  if ($target eq 'web' || $target eq 'webgrade') {
    my $output=&Apache::lonxml::endredirection;
    my $href= &Apache::lonxml::get_param('href',$parstack,$safeeval);
    if (!$href) { $href='/adm/rat/empty.html'; }
    my $width= &Apache::lonxml::get_param('width',$parstack,$safeeval);
    if (!$width) { $width='500'; }
    my $height= &Apache::lonxml::get_param('height',$parstack,$safeeval);
    if (!$height) { $height='200'; }
    $result=&Apache::loncommon::modal_link($href,$output,$width,$height);
  } else {
      $result = '';
  }
  return $result;
}


sub start_togglebox {
    my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
    my $result = '';
    if ($target eq 'web' || $target eq 'webgrade') {
        my $id="LONCAPA_togglebox_$Apache::lonxml::curdepth";
        my $heading=&Apache::lonxml::get_param('heading',$parstack,$safeeval);
        unless ($heading) { $heading=''; } else { $heading.=' '; }
        my $showtext=&Apache::lonxml::get_param('showtext',$parstack,$safeeval);
        my $hidetext=&Apache::lonxml::get_param('hidetext',$parstack,$safeeval);
        my $headerbg=&Apache::lonxml::get_param('headerbg',$parstack,$safeeval);
        $result=&Apache::loncommon::start_togglebox($id,$heading,$headerbg,$hidetext,$showtext);
    } elsif ($target eq 'tex') {
        my $heading=&Apache::lonxml::get_param('heading',$parstack,$safeeval);
        unless ($heading) { $heading=''; } else { $heading.=' '; }
        $result = "\n\n".'\fbox{{\bf '.$heading.'} \qquad '."\n";
    } elsif ($target eq 'edit') {
        $result.=&Apache::edit::tag_start($target,$token);
        $result.=&Apache::edit::text_arg('Heading:','heading',$token,70);
        $result.=&Apache::edit::text_arg('Header Background:','headerbg',$token,7);
        $result.=&Apache::edit::text_arg('Show text:','showtext',$token,10);
        $result.=&Apache::edit::text_arg('Hide text:','hidetext',$token,10);
        $result .=&Apache::edit::end_row().&Apache::edit::start_spanning_row();
    } elsif ($target eq 'modified') {
        my $constructtag=&Apache::edit::get_new_args($token,$parstack,
                                                     $safeeval,'heading',
                                                     'showtext','hidetext',
                                                     'headerbg','textbg');
        if ($constructtag) { $result=&Apache::edit::rebuild_tag($token); }
    }
    return $result;
}

sub end_togglebox {
  my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
  my $result;
  if ($target eq 'web' || $target eq 'webgrade') {
    $result=&Apache::loncommon::end_togglebox();
  } elsif ($target eq 'tex') {
      $result = "}\n\n";
  } else {
      $result = '';
  }
  return $result;
}



sub start_import {
  my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
  my $bodytext=$$parser[$#$parser]->get_text("/import");
  my $result ="";

  $bodytext=&Apache::run::evaluate($bodytext,$safeeval,$$parstack[$#$parstack]);

  if ($target eq 'web' ||  $target eq 'webgrade' || $target eq 'grade' 
      || $target eq 'answer' || $target eq 'tex' || $target eq 'analyze' ) {
    # FIXME this probably needs to be smart about construction vs.
    # non construction space.
    my $location=&Apache::lonnet::filelocation($Apache::lonxml::pwd['-1'],$bodytext);
    my $file=&Apache::lonnet::getfile($location);
    if ($file == -1) {
      &Apache::lonxml::error("<b> Unable to find <i>$bodytext as $location</i> for import</b>");
      return "";
    }
    my $importmode=&Apache::lonxml::get_param('importmode',$parstack,$safeeval);
    if (($importmode eq 'problem') || ($importmode eq 'part')) {
# We are using import to import published problems
       if (($importmode eq 'problem') || ($file=~/<part[^<]*>/s)) {
# We explicitly don't want this to be a separate part or the problem already has parts
          $file=~s/^\s*<problem>/<library>/s;
	  $file=~s/<\/problem>\s*$/<\/library>/s;
       } else {
# We want this to be a separate part, but it currently is not
          $file=~s/^\s*<problem>/<library><part>/s;
	  $file=~s/<\/problem>\s*$/<\/part><\/library>/s;
       }
    }
    my $dir=$location;
    $dir=~s:/[^/]*$::;
    #  &Apache::lonxml::debug("directory $dir $location file $file \n<b>END</b>\n");
    my $id= &Apache::lonxml::get_id($parstack,$safeeval);
    if (!$id) { $id=$Apache::lonxml::curdepth; }
    push(@Apache::inputtags::import,$id);
    push(@Apache::inputtags::importlist,$id);

    &Apache::lonxml::newparser($parser,\$file,$dir);

  } elsif ($target eq "edit" ) {
    $result.=&Apache::edit::tag_start($target,$token);
    my $location=$token->[1];
    $location=~s/^\s*//s;
    $location=~s/\s*$//s;
    $result.=&Apache::edit::editline($location,$bodytext,'',40);
    $result.=&Apache::edit::browse(undef,'textnode');
    $result.= '&nbsp;<label>'.&mt('Import as:').
              '<select name="importmode_'.$Apache::lonxml::curdepth.'">';
    my %options=&Apache::lonlocal::texthash(''        => 'as standard library',
                                            'problem' => 'as problem',
                                            'part'    => 'as problem part(s)');
    foreach my $option (sort(keys(%options))) {
       $result.='<option value="'.$option.'"';
       if ($option eq &Apache::lonxml::get_param('importmode',$parstack,$safeeval)) {
          $result.=' selected="selected"';
       }
       $result.='>'.$options{$option}.'</option>';
    }
    $result.='</select></label>';
    #FIXME this need to convert $bodytext to be a contruction space reference
    #my $location=&Apache::lonnet::filelocation($Apache::lonxml::pwd['-1'],$bodytext);
    #$result.="Click<a href=\"$location\">here</a> to edit<br />"
  } elsif ($target eq 'modified') {
      &Apache::edit::get_new_args($token,$parstack,$safeeval,'importmode');
      $result='<import id="'.$token->[2]{'id'}.'" importmode="'.$token->[2]{'importmode'}.'">';
      $result.=&Apache::edit::modifiedfield("/import",$parser);
  } elsif ($target eq 'meta') {
    my $id= &Apache::lonxml::get_id($parstack,$safeeval);
    $result.='<import part="'.$Apache::inputtags::part;
    if ($id) {
      $result.='" id="'.$id;
    }
    $result.='" importmode="'.$token->[2]{'importmode'}.'">';
    $result.=$bodytext;
    $result.='</import>';
  }
  return $result;
}

sub end_import {
  my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
  pop(@Apache::inputtags::import);
  my $result;
  if ($target eq 'edit' ) { $result=&Apache::edit::end_row.
				&Apache::edit::end_table(); }
  return $result;
}

sub start_storetc {
  my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
  my $result = '';
  &Apache::lonxml::startredirection;
  return $result; 
}

sub end_storetc {
    my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
    my $result;
    my $output=&Apache::lonxml::endredirection;
    $output =~ s/\"/\&quot\;/g;
    $result = '{\bf '.$output.'.}}\write\tcfile{\protect\tcpc{ '.$output.'.}{\the\value{relpage}}}';
    return $result;
}


sub start_physnet {
    my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
    my $bodytext = '/adm/includes/physnet.sty';
    my $location=&Apache::lonnet::filelocation($Apache::lonxml::pwd['-1'],$bodytext);
    my $cbistyletext=&Apache::lonnet::getfile($location);

    %$style = (%$style,&Apache::style::styleparser($target,$cbistyletext));
    $$parser['-1']->unget_token($token);
#    if ( defined($$style{'physnet'}) ) {
#        &Apache::lonxml::newparser($parser,\$$style{'physnet'});
#    }
    return "";
}

sub end_physnet {
  return '';
}

sub start_standalone {
  my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
  my $result='';
  if ($target eq 'web' || $target eq 'webgrade') {
    if ( $env{'request.course.id'} ) {
      my $inside = &Apache::lonxml::get_all_text("/standalone",$parser,$style);
    } else {
      $result='<table bgcolor="#E1E1E1" border="2"><tr><td>';
    }
  }
  return $result;
}

sub end_standalone {
  my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
  my $result='';
  if ($target eq 'web' || $target eq 'webgrade' ) {
    if ( $env{'request.course.id'} ) {
    } else {
      $result='</td></tr></table>';
    }
  }
  return $result;
}

sub start_comment {
  my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
  my $result='';
  if ($target eq 'edit') {
    $result=&Apache::edit::tag_start($target,$token);
    my $bodytext=&Apache::lonxml::get_all_text("/comment",$parser,$style);
    $result.=&Apache::edit::editfield($token->[1],$bodytext,'',80,4)
  } elsif ( $target eq 'modified') {
    $result=$token->[4].&Apache::edit::modifiedfield("/comment",$parser);
  } elsif ( $target eq 'web'    || $target eq 'tex'  || $target eq 'grade'   ||
	    $target eq 'answer' || $target eq 'meta' || $target eq 'analyze' ||
	    $target eq 'webgrade') {
    #normally throw away comments
    my $bodytext=&Apache::lonxml::get_all_text("/comment",$parser,$style);
  }
  return $result;
}

sub end_comment {
  my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_;
  if ($target eq 'edit' ) { return &Apache::edit::end_table(); }
  return '';
}


sub xmlparse {
  my ($string) = @_;
  &Apache::lonxml::debug("xmlparse recursion starting with $string");
  # Apache::run::evaluate does an 'eval' on the name of the subroutine
  # if it detects something that looks like a subroutine, this ends up calling
  # things without any arguments and since perl is nice enough to pass
  # along the default arguments when you don't explicitly say no arguments
  # if you call &xmlparse, it gets &xmlparse passed as it argument.
  # Same thing soccurs with &chemparse.
  if ($string eq '&xmlparse') { return '&xmlparse'; }
  if ($string eq '&chemparse') { return '&chemparse'; }
  my ($target,$token,$tagstack,$parstack,$oldparser,$safeeval,$style)=
    @Apache::scripttag::parser_env;
  my @parser;
  &Apache::lonxml::newparser(\@parser,\$string);
  &Apache::lonxml::startredirection();
  my $result=&Apache::lonxml::inner_xmlparse($target,$tagstack,
					     $parstack,\@parser,
					     $safeeval,$style);
  $result.=&Apache::lonxml::endredirection();
  &Apache::lonxml::debug("target is $target xmlparse recursion ending with $result");
  return $result;
}

sub start_num {
    my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style) = @_;
    my $result = '';
    my $inside = &Apache::lonxml::get_all_text_unbalanced("/num",$parser);
    if ($target eq 'tex' || $target eq 'web' || $target eq 'webgrade') {
	$inside=&Apache::run::evaluate($inside,$safeeval,$$parstack[-1]);
	if (!$Apache::lonxml::default_homework_loaded) {
	    &Apache::lonxml::default_homework_load($safeeval);
	}
	@Apache::scripttag::parser_env = @_;
	my $format=&Apache::lonxml::get_param('format',$parstack,$safeeval);
	$result=&Apache::run::run("return &prettyprint(q\0$inside\0,q\0$format\0);",$safeeval);
    }    
    return $result;
}

sub end_num {
    my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style) = @_;
    my $result = '';
    return $result;
}

sub start_parse {
    my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style) = @_;
    my $result = '';
    if ( $target eq 'web'    || $target eq 'tex'    ||
	 $target eq 'grade'  || $target eq 'answer' ||
	 $target eq 'analyze'|| $target eq 'webgrade') {
	my $inside = &Apache::lonxml::get_all_text_unbalanced("/parse",$parser);
	$inside=&Apache::run::evaluate($inside,$safeeval,$$parstack[-1]);
	if (!$Apache::lonxml::default_homework_loaded) {
	    &Apache::lonxml::default_homework_load($safeeval);
	}
	@Apache::scripttag::parser_env = @_;
	$result=&Apache::run::run("return &xmlparse(q\0$inside\0);",$safeeval);
	if ($target eq 'grade' || $target eq 'answer' ||
	    $target eq 'analyze') {
	    # grade/answer/analyxe should produce no output but if we
	    # are redirecting, the redirecter should know what to do
	    # with the output
	    if (!$Apache::lonxml::redirection) { $result=''; }
	}
    }
    return $result;
}

sub end_parse {
    my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style) = @_;
    my $result = '';
    return $result;
}

sub start_algebra {
    my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style) = @_;
    my $result = '';
    if ( $target eq 'web'     || $target eq 'tex'    ||
	 $target eq 'grade'   || $target eq 'answer' ||
	 $target eq 'analyze' || $target eq 'webgrade') {
	my $inside = &Apache::lonxml::get_all_text_unbalanced("/algebra",$parser);
	$inside = &Apache::run::evaluate($inside,$safeeval,$$parstack[-1]);
	if ($target eq 'web' || $target eq 'tex' || $target eq 'analyze') {
	    my $style=&Apache::lonxml::get_param('style',$parstack,$safeeval);
	    $result=&Apache::lontexconvert::algebra($inside,$target,$style,$parstack,$safeeval);
	}
	$Apache::lonxml::post_evaluate=0;
    }
    return $result;
}

sub end_algebra {
    my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style) = @_;
    my $result = '';
    return $result;
}

1;
__END__

=pod

=head1 NAME

Apache::scripttag.pm

=head1 SYNOPSIS

implements <script>, <scriptlib>, <parserlib>,
and <import>

This is part of the LearningOnline Network with CAPA project
described at http://www.lon-capa.org.

=cut


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>