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, 4 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

    1: # The LearningOnline Network with CAPA
    2: # <script> definiton
    3: #
    4: # $Id: scripttag.pm,v 1.173 2015/01/19 15:36:16 goltermann Exp $
    5: #
    6: # Copyright Michigan State University Board of Trustees
    7: #
    8: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
    9: #
   10: # LON-CAPA is free software; you can redistribute it and/or modify
   11: # it under the terms of the GNU General Public License as published by
   12: # the Free Software Foundation; either version 2 of the License, or
   13: # (at your option) any later version.
   14: #
   15: # LON-CAPA is distributed in the hope that it will be useful,
   16: # but WITHOUT ANY WARRANTY; without even the implied warranty of
   17: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   18: # GNU General Public License for more details.
   19: #
   20: # You should have received a copy of the GNU General Public License
   21: # along with LON-CAPA; if not, write to the Free Software
   22: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   23: #
   24: # /home/httpd/html/adm/gpl.txt
   25: #
   26: # http://www.lon-capa.org/
   27: #
   28: 
   29: package Apache::scripttag;
   30: 
   31: use strict;
   32: use Apache::lonnet;
   33: use Apache::lonlocal;
   34: use Apache::lonxml();
   35: use Apache::londefdef();
   36: use Apache::style();
   37: 
   38: #Globals
   39: # this used to pass around the standard callsub arguments to a tag func
   40: # so xmlparse can reenter the inner_xmlparse loop.
   41: 
   42: @Apache::scripttag::parser_env = ();
   43: BEGIN {
   44:   &Apache::lonxml::register('Apache::scripttag',
   45: 			    ('script','scriptlib','parserlib','import',
   46: 			     'window','windowlink','togglebox','display','storetc','physnet',
   47: 			     'standalone','comment','num','parse','algebra',
   48: 			     'LONCAPA_INTERNAL_TURN_STYLE_ON',
   49: 			     'LONCAPA_INTERNAL_TURN_STYLE_OFF'));
   50: }
   51: 
   52: sub start_LONCAPA_INTERNAL_TURN_STYLE_ON {
   53:     $Apache::lonxml::usestyle=1;
   54:     $Apache::lonxml::style_values='';
   55:     return ('','no');
   56: }
   57: 
   58: sub end_LONCAPA_INTERNAL_TURN_STYLE_ON {
   59:     my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_;
   60:     my $end=&Apache::lonxml::get_param('end',$parstack,$safeeval);
   61:     if (defined($end)) {
   62: 	&Apache::lonxml::end_tag($tagstack,$parstack,$token);
   63:     }
   64:     return ('','no');
   65: }
   66: 
   67: sub start_LONCAPA_INTERNAL_TURN_STYLE_OFF {
   68:     my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_;
   69:     $Apache::lonxml::usestyle=0;
   70:     my $end=&Apache::lonxml::get_param('end',$parstack,$safeeval);
   71:     if (!$end) {
   72: 	$Apache::lonxml::style_values=$$parstack[-1];
   73: 	$Apache::lonxml::style_end_values=$$parstack[-1];
   74:     } else {
   75: 	$Apache::lonxml::style_values=$Apache::lonxml::style_end_values;
   76: 	$Apache::lonxml::style_end_values='';
   77:     }
   78:     return ('','no');
   79: }
   80: 
   81: sub end_LONCAPA_INTERNAL_TURN_STYLE_OFF {
   82:     return ('','no');
   83: }
   84: 
   85: sub start_script {
   86:   my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_;
   87:   @Apache::scripttag::parser_env = @_;
   88:   my $result='';
   89:   my $type= &Apache::lonxml::get_param('type',$parstack,$safeeval);
   90:   &Apache::lonxml::debug("found type of $type");
   91:   if ($type eq "loncapa/perl") {
   92:     if ( $target eq "modified" ) {
   93: 	$result=$token->[4].&Apache::edit::modifiedfield('/script',$parser);
   94:     } elsif ( $target eq 'web' || $target eq 'tex' ||
   95: 	      $target eq 'grade' || $target eq 'webgrade' ||
   96: 	      $target eq 'answer' || $target eq 'analyze' ) {
   97: 	my $bodytext=&Apache::lonxml::get_all_text_unbalanced("/script",$parser);
   98: 	if (!$Apache::lonxml::default_homework_loaded) {
   99: 	    &Apache::lonxml::default_homework_load($safeeval);
  100: 	}
  101: 	&Apache::run::run($bodytext,$safeeval);
  102: 	if (($target eq 'answer') &&
  103: 	    ($env{'form.answer_output_mode'} ne 'tex') &&
  104: 	    ($Apache::lonhomework::viewgrades == 'F')) {
  105: 	    $Apache::lonxml::evaluate--;
  106: 	    my (undef,undef,$udom,$uname)=&Apache::lonnet::whichuser();
  107: 	    $uname =~s/\W//g;
  108: 	    $udom  =~s/\W//g;
  109: 	    my $function_name = 
  110: 		join('_','LONCAPA_scriptvars',$uname,$udom,
  111: 		     $env{'form.counter'},$Apache::lonxml::curdepth);
  112:             &Apache::lonxml::add_script_result(
  113: 	             &Apache::loncommon::modal_adhoc_window($function_name,500,500,
  114:                             '<pre style="background-color:#ffffff;">'.
  115:                             &Apache::run::dump($target,$safeeval).'</pre>',
  116:                             &mt('Script Vars'))."<br />");
  117: 	}
  118:     } elsif ($target eq "edit" ) {
  119:       #&Apache::run::run($bodytext,$safeeval);
  120:       #$result="<br /> &lt;$token->[1]&gt; output: <br />$bodytext<br />Source:<br />";
  121:     	my $bodytext=&Apache::lonxml::get_all_text_unbalanced("/script",$parser);
  122:     	$result=&Apache::edit::tag_start($target,$token,'Script');
  123: 
  124:         my $depth = $Apache::lonxml::curdepth;
  125:         $result.='<span id="LC_edit_problem_codemirror">';
  126:         unless ($env{'environment.nocodemirror'}) {
  127:             # only show button if codemirror activated
  128:             $result.='<input type="button" id="fitsize'.$depth.'" value="'.&mt("Dynamic size").
  129:             '" onclick="autosize(\''.$depth.'\')" />';
  130:         }
  131:         $result.=&Apache::edit::editfield($token->[1],$bodytext,'',80,4).'</span>';
  132: 
  133:         unless ($env{'environment.nocodemirror'}) {
  134:             $result.='<script type="text/javascript">
  135:                 var cm'.$depth.' = CodeMirror.fromTextArea(document.getElementById("homework_edit_'.$depth.'"),
  136:                 {
  137:                     mode: "perl",
  138:                     lineWrapping: true,
  139:                     lineNumbers: true,
  140:                     tabSize: 4,
  141:                     indentUnit: 4,
  142:                     autoCloseBrackets: true,
  143:                     styleActiveLine: true,
  144:                     
  145:                     extraKeys: {
  146:                         "Tab": "indentMore",
  147:                         "Shift-Tab": "indentLess"
  148:                     }
  149:                 });
  150:                 if(sessionStorage.getItem("autosized_'.$depth.'") != null) {
  151:                     document.getElementById("fitsize'.$depth.'").value = "'.&mt("Fixed size").'";
  152:                     cm'.$depth.'.setSize("","auto");
  153:                 }
  154:             </script>';
  155:         }
  156:                 
  157: 
  158:     } elsif ($target eq 'meta') {
  159: 	my $bodytext=&Apache::lonxml::get_all_text_unbalanced("/script",$parser);
  160:     }
  161:   } else {
  162:       my $bodytext=&Apache::lonxml::get_all_text_unbalanced("/script",$parser);
  163:       if ($target ne "meta" && $target ne 'tex' && $target ne 'answer') {
  164: 	  $result = $token->[4];
  165: 	  $result.=$bodytext;
  166:           my $src=&Apache::lonxml::get_param('src',$parstack,$safeeval,undef,1);
  167:           my $url=&Apache::lonnet::hreflocation('',$env{'request.filename'});
  168:           my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
  169:           my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
  170:           if ($src ne '') {
  171:               if ($src !~ m{^(/|https?://)}) {
  172:                   my $cleanhref = &Apache::londefdef::clean_docs_httpref($src,$url,$cdom,$cnum);
  173:                   if ($cleanhref) {
  174:                       &Apache::lonxml::extlink($cleanhref);
  175:                   }
  176:               }
  177:           } elsif (($type eq 'text/javascript') && ($bodytext ne '')) {
  178:               if ($url =~ m{^\Q/uploaded/$cdom/$cnum/\E(docs|supplemental)/}) {
  179:                   if ($bodytext =~ m{\.addMediaSrc\((["'])((?!\1).)+\1\);}) {
  180:                       my $quote = $1;
  181:                       if ($bodytext =~ m{\Q.addMediaSrc($quote\E([^$quote]+)\Q$quote)\E}) {
  182:                           my $fname = $1;
  183:                           my $cleanhref =
  184:                               &Apache::londefdef::clean_docs_httpref($fname,$url,$cdom,$cnum);
  185:                           if ($cleanhref) {
  186:                               &Apache::lonxml::extlink($cleanhref);
  187:                           }
  188:                       }
  189:                   }
  190:                   if ($bodytext =~ m{\.set\w+(Src|Swf)\(["']}i) {
  191:                       my @srcs = split(/\.set/,$bodytext);
  192:                       if (scalar(@srcs) > 1) {
  193:                           foreach my $item (@srcs) {
  194:                               if ($item =~ m{^(FlashPlayerSwf|MediaSrc|XMPSrc|ConfigurationSrc|PosterImageSrc)\((['"])(?:(?!\2).)+\2\)}is) {
  195:                                   my $srctype = $1;
  196:                                   my $quote = $2;
  197:                                   my ($fname) = ($item =~ m{^\Q$srctype($quote\E([^$quote]+)\Q$quote)\E}); 
  198:                                   my $cleanhref =
  199:                                       &Apache::londefdef::clean_docs_httpref($fname,$url,$cdom,$cnum);
  200:                                   if ($cleanhref) {
  201:                                       &Apache::lonxml::extlink($cleanhref);
  202:                                       if ($srctype eq 'ConfigurationSrc') {
  203:                                           if ($cleanhref =~ m{^(.+/)configuration_express\.xml$}) {
  204: #
  205: # Camtasia 8.1: express_show/spritesheet.png needed, and included in zip archive.
  206: # Not referenced directly in <main>.html or <main>_player.html files,
  207: # so call lonxml::extlink() here to include httpref for the uploaded file.
  208: # (where <main> is name user gave to file/archive).
  209: #
  210: 
  211:                                               my $spritesheet = $1.'express_show/spritesheet.png';
  212:                                               if (&Apache::lonnet::repcopy_userfile($spritesheet) eq 'ok') {
  213:                                                   &Apache::lonxml::extlink($spritesheet);
  214:                                               }
  215:                                           }
  216: #
  217: # Camtasia 8.4: express_show/spritesheet.min.css needed, and included in zip archive.
  218: # Not referenced directly in <main>.html or <main>_player.html files,
  219: # so call lonxml::extlink() here to include httpref for the uploaded file.
  220: # (where <main> is name user gave to file/archive).
  221: #
  222:                                           my $spritesheet_css = $1.'express_show/spritesheet.min.css';
  223:                                           if (&Apache::lonnet::repcopy_userfile($spritesheet_css) eq 'ok') {
  224:                                               &Apache::lonxml::extlink($spritesheet_css);
  225:                                           }
  226:                                       } elsif ($srctype eq 'PosterImageSrc') {
  227:                                           if ($fname =~ m{^(.+)_First_Frame\.png$}) {
  228:                                               my $prefix = $1;
  229:                                               my ($path) = ($cleanhref =~ m{^(.+/)\Q$fname\E});
  230: #
  231: # Camtasia 8.1: <main>_Thumbnails.png needed, and included in zip archive.
  232: # Not referenced directly in <main>.html or <main>_player.html files,
  233: # so call lonxml::extlink() here to include httpref for the uploaded file
  234: # (where <main> is name user gave to file/archive).
  235: #
  236:                                               my $thumbnail = $path.$prefix.'_Thumbnails.png';
  237:                                               if (&Apache::lonnet::repcopy_userfile($thumbnail) eq 'ok') {
  238:                                                   &Apache::lonxml::extlink($thumbnail);
  239:                                               }
  240:                                           }
  241:                                       }
  242:                                   }
  243:                               }
  244:                           }
  245:                       }
  246:                   }
  247:                   if ($bodytext =~ /\(document,\s*(['"])script\1,\s*\[([^\]]+)\]\);/s) {
  248:                       my $scriptslist = $2;
  249:                       my @srcs = split(/\s*,\s*/,$scriptslist);
  250:                       foreach my $src (@srcs) {
  251:                           if ($src =~ /(["'])(?:(?!\1).)+\.js\1/) {
  252:                               my $quote = $1;
  253:                               my ($fname) = ($src =~ m/\Q$quote\E([^$quote]+)\Q$quote\E/);
  254:                               my $cleanhref =
  255:                                   &Apache::londefdef::clean_docs_httpref($fname,$url,$cdom,$cnum);
  256:                               if ($cleanhref) {
  257:                                   &Apache::lonxml::extlink($cleanhref);
  258:                               }
  259:                           }
  260:                       }
  261:                   }
  262:                   if ($bodytext =~ m{loadScript\(\s*(['"])((?:(?!\1).)+\.js)\1,\s*function}is) {
  263:                       my $fname = $2;
  264:                       if ($fname) {
  265:                           my $cleanhref =
  266:                               &Apache::londefdef::clean_docs_httpref($fname,$url,$cdom,$cnum);
  267:                           if ($cleanhref) {
  268:                               &Apache::lonxml::extlink($cleanhref);
  269:                           }
  270:                       }
  271:                   }
  272:               }
  273:           }
  274:       }
  275:   }
  276:   return $result;
  277: }
  278: 
  279: sub end_script {
  280:   my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_;
  281:   if ( $target eq "meta" ) { return ''; } 
  282:   my $type = &Apache::lonxml::get_param('type',$parstack,$safeeval);
  283:   my $result='';
  284:   #other script blocks need to survive
  285:   if ($type ne "loncapa/perl" && $target ne 'tex') {
  286:     return $token->[2];
  287:   } elsif ($target eq 'edit' ) {
  288:     return &Apache::edit::end_table();
  289:   } elsif ($target eq 'answer') {
  290:     $Apache::lonxml::evaluate++;
  291:   }
  292:   return '';
  293: }
  294: 
  295: sub start_display {
  296:   my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_;
  297:   @Apache::scripttag::parser_env = @_;
  298:   my $result;
  299: 
  300:   if ( $target eq "modified" ) {
  301:       $result=$token->[4].&Apache::edit::modifiedfield("/display",$parser);
  302:   } elsif ( $target eq 'web' || $target eq 'tex' ||
  303: 	    $target eq 'grade' || $target eq 'webgrade' ||
  304: 	    $target eq 'answer' || $target eq 'analyze') {
  305:       my $bodytext=&Apache::lonxml::get_all_text_unbalanced("/display",$parser);
  306:       if (!$Apache::lonxml::default_homework_loaded) {
  307: 	  &Apache::lonxml::default_homework_load($safeeval);
  308:       }
  309:       $result=&Apache::run::run($bodytext,$safeeval);
  310:       if ($target eq 'grade' || $target eq 'answer' ||
  311: 	  $target eq 'analyze') {
  312: 	  # grade/answer/analyxe should produce no output but if we
  313: 	  # are redirecting, the redirecter should know what to do
  314: 	  # with the output
  315: 	  if (!$Apache::lonxml::redirection) { $result=''; }
  316:       }
  317:       $Apache::lonxml::post_evaluate=0;
  318:   } elsif ($target eq "edit" ) {
  319:     my $bodytext=&Apache::lonxml::get_all_text_unbalanced("/display",$parser);
  320:     #$result = 
  321:     #  "<br /> &lt;$token->[1]&gt; output: <br />$bodytext<br />Source:<br />";
  322:     #$result.=&Apache::edit::editfield($token->[1],$bodytext,'',40,1);
  323:     $result=&Apache::edit::tag_start($target,$token,'Script With Display');
  324:     $result.=&Apache::edit::editfield($token->[1],$bodytext,'',80,1)
  325:   } elsif ($target eq 'meta') {
  326:       my $bodytext=&Apache::lonxml::get_all_text_unbalanced("/display",$parser);
  327:   }
  328:   return $result;
  329: }
  330: 
  331: sub end_display {
  332:   my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_;
  333:   if ($target eq 'edit' ) { return &Apache::edit::end_table(); }
  334:   return '';
  335: }
  336: 
  337: sub start_scriptlib {
  338:   my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
  339:   my $bodytext;
  340:   my $result ='';
  341:   my $error='';
  342: 
  343:   if ($target eq 'web' || $target eq 'tex' || $target eq 'grade' ||
  344:       $target eq 'meta' || $target eq 'edit' || $target eq 'answer' ||
  345:       $target eq 'analyze' || $target eq 'webgrade') {
  346:     $bodytext=$$parser[$#$parser]->get_text("/scriptlib");
  347:     $bodytext=&Apache::run::evaluate($bodytext,$safeeval,
  348: 				     $$parstack[$#$parstack]);
  349:     my $location=&Apache::lonnet::filelocation($Apache::lonxml::pwd['-1'],
  350: 					       $bodytext);
  351:     my $script=&Apache::lonnet::getfile($location);
  352:     if ($script == -1) {
  353:       if ($target eq 'edit') {
  354:         $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";
  355:       } else {
  356: 	&Apache::lonxml::error("<b> Unable to find <i>$location</i> for scriptlib</b>");
  357: 	return "";
  358:       }
  359:     }
  360:     &Apache::run::run($script,$safeeval);
  361:     #&Apache::lonxml::debug("ran $bodytext:<br />".&Apache::lonnet::getfile($bodytext)."<br />");
  362:   }
  363:   if ($target eq "edit" ) {
  364:     $result=
  365:       &Apache::edit::tag_start($target,$token,'New Script Functions').
  366: 	&Apache::edit::editline($token->[1],$bodytext,'scriptlib',40).
  367:             &Apache::edit::browse(undef,'textnode').
  368: 	  $error.'</td></tr>'.
  369: 	    &Apache::edit::end_table();
  370:   }
  371:   if ($target eq "modified" ) {
  372:       $result=$token->[4].&Apache::edit::modifiedfield("/scriptlib",$parser);
  373:   }
  374:   return $result;
  375: }
  376: 
  377: sub end_scriptlib {
  378:   my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
  379:   my @result;
  380:   if ($target eq "edit" ) { $result[1]='no'; }
  381:   return @result;
  382: }
  383: 
  384: sub start_parserlib {
  385:   my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
  386:   my $bodytext;
  387:   my $result ="";
  388:   my $error='';
  389:   if ($target eq 'web' || $target eq 'tex' || $target eq 'grade' ||
  390:       $target eq 'meta' || $target eq 'edit' || $target eq 'answer' ||
  391:       $target eq 'analyze' || $target eq 'webgrade') {
  392:     $bodytext=$$parser[$#$parser]->get_text("/parserlib");
  393:     $bodytext=&Apache::run::evaluate($bodytext,$safeeval,
  394: 				     $$parstack[$#$parstack]);
  395:     my $location=&Apache::lonnet::filelocation($Apache::lonxml::pwd['-1'],
  396: 					       $bodytext);
  397:     my $styletext=&Apache::lonnet::getfile($location);
  398:     #&Apache::lonxml::debug("found :$bodytext: in :$location: with :$styletext:");
  399:     if ($styletext == -1) {
  400:       if ($target eq 'edit') {
  401: 	$error='</tr><tr><td>Errors</td><td colspan="2"><b> Unable to find <i>'.$location.'</i></b></td>'."\n";
  402:       } else {
  403: 	&Apache::lonxml::error("<b> Unable to find <i>$location</i> for parserlib</b>");
  404: 	return "";
  405:       }
  406:     }
  407:     %$style = ( %$style , &Apache::style::styleparser($target,$styletext));
  408:   }
  409:   if ($target eq "edit" ) {
  410:     $result=
  411:       &Apache::edit::tag_start($target,$token,'New Tag Definitions').
  412: 	&Apache::edit::editline($token->[1],$bodytext,'',40).
  413: 	  $error.'</td></tr>'.
  414: 	    &Apache::edit::end_table();
  415:   }
  416:   if ($target eq "modified" ) {
  417:       $result=$token->[4].&Apache::edit::modifiedfield("/parserlib",$parser);
  418:   }
  419:   return $result;
  420: }
  421: 
  422: sub end_parserlib {
  423:   my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
  424:   my @result;
  425:   if ($target eq "edit" ) { $result[1]='no'; }
  426:   return @result;
  427: }
  428: 
  429: sub start_window {
  430:     my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
  431:     my $result = '';
  432:     if ($target eq 'web' || $target eq 'webgrade') {
  433: 	&Apache::lonxml::startredirection;
  434:     } elsif ($target eq 'tex') {
  435:         my $printtext=&Apache::lonxml::get_param('printtext',$parstack,$safeeval);
  436:         if ($printtext=~/\w/) {
  437: # If printtext is given, do not output any intervening information
  438:            &Apache::lonxml::startredirection;
  439:         } else {
  440:            $result = '\unskip\footnote{';
  441:         }
  442:     } elsif ($target eq 'edit') {
  443: 	$result.=&Apache::edit::tag_start($target,$token);
  444: 	$result.=&Apache::edit::text_arg('Text of Link:','linktext',$token,70);
  445: 	$result.=&Apache::edit::text_arg('Height:','height',$token,5);
  446: 	$result.=&Apache::edit::text_arg('Width:','width',$token,5);
  447:         $result.=&Apache::edit::text_arg('Printed text (optional):','printtext',$token,20);
  448: 	$result .=&Apache::edit::end_row().&Apache::edit::start_spanning_row();
  449:     } elsif ($target eq 'modified') {
  450: 	my $constructtag=&Apache::edit::get_new_args($token,$parstack,
  451: 						     $safeeval,'linktext',
  452: 						     'width','height');
  453: 	if ($constructtag) { $result=&Apache::edit::rebuild_tag($token); }
  454:     }
  455:     return $result;  
  456: }
  457: 
  458: sub end_window {
  459:   my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
  460:   my $result;
  461:   if ($target eq 'web' || $target eq 'webgrade') {
  462:     my $output=&Apache::lonxml::endredirection;
  463:     my $linktext= &Apache::lonxml::get_param('linktext',$parstack,$safeeval);
  464:     if (!$linktext) { $linktext='<sup>*</sup>'; }
  465:     my $width= &Apache::lonxml::get_param('width',$parstack,$safeeval);
  466:     if (!$width) { $width='500'; }
  467:     my $height= &Apache::lonxml::get_param('height',$parstack,$safeeval);
  468:     if (!$height) { $height='200'; }
  469:     $result=&Apache::loncommon::modal_adhoc_window
  470:            ("LONCAPA_newwindow_$Apache::lonxml::curdepth",$width,$height,$output,$linktext);
  471:   } elsif ($target eq 'tex') {
  472:       my $printtext=&Apache::lonxml::get_param('printtext',$parstack,$safeeval);
  473:       if ($printtext=~/\w/) {
  474: # If a "printtext" is given, proceed to retrieve all intervening information and trash it
  475:          my $output=&Apache::lonxml::endredirection;
  476: # Use printtext instead
  477:          $result=$printtext;
  478:       } else {
  479:          $result='}';
  480:       }
  481:   } else {
  482:       $result = '';
  483:   }
  484:   return $result; 
  485: }
  486: 
  487: 
  488: sub start_windowlink {
  489:     my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
  490:     my $result = '';
  491:     if ($target eq 'web' || $target eq 'webgrade') {
  492:         &Apache::lonxml::startredirection;
  493:     } elsif ($target eq 'edit') {
  494:         $result.=&Apache::edit::tag_start($target,$token);
  495:         $result.=&Apache::edit::text_arg('Link:','href',$token,70);
  496:         $result.=&Apache::edit::text_arg('Height:','height',$token,5);
  497:         $result.=&Apache::edit::text_arg('Width:','width',$token,5);
  498:         $result .=&Apache::edit::end_row().&Apache::edit::start_spanning_row();
  499:     } elsif ($target eq 'modified') {
  500:         my $constructtag=&Apache::edit::get_new_args($token,$parstack,
  501:                                                      $safeeval,'href',
  502:                                                      'width','height');
  503:         if ($constructtag) { $result=&Apache::edit::rebuild_tag($token); }
  504:     }
  505:     return $result;
  506: }
  507: 
  508: sub end_windowlink {
  509:   my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
  510:   my $result;
  511:   if ($target eq 'web' || $target eq 'webgrade') {
  512:     my $output=&Apache::lonxml::endredirection;
  513:     my $href= &Apache::lonxml::get_param('href',$parstack,$safeeval);
  514:     if (!$href) { $href='/adm/rat/empty.html'; }
  515:     my $width= &Apache::lonxml::get_param('width',$parstack,$safeeval);
  516:     if (!$width) { $width='500'; }
  517:     my $height= &Apache::lonxml::get_param('height',$parstack,$safeeval);
  518:     if (!$height) { $height='200'; }
  519:     $result=&Apache::loncommon::modal_link($href,$output,$width,$height);
  520:   } else {
  521:       $result = '';
  522:   }
  523:   return $result;
  524: }
  525: 
  526: 
  527: sub start_togglebox {
  528:     my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
  529:     my $result = '';
  530:     if ($target eq 'web' || $target eq 'webgrade') {
  531:         my $id="LONCAPA_togglebox_$Apache::lonxml::curdepth";
  532:         my $heading=&Apache::lonxml::get_param('heading',$parstack,$safeeval);
  533:         unless ($heading) { $heading=''; } else { $heading.=' '; }
  534:         my $showtext=&Apache::lonxml::get_param('showtext',$parstack,$safeeval);
  535:         my $hidetext=&Apache::lonxml::get_param('hidetext',$parstack,$safeeval);
  536:         my $headerbg=&Apache::lonxml::get_param('headerbg',$parstack,$safeeval);
  537:         $result=&Apache::loncommon::start_togglebox($id,$heading,$headerbg,$hidetext,$showtext);
  538:     } elsif ($target eq 'tex') {
  539:         my $heading=&Apache::lonxml::get_param('heading',$parstack,$safeeval);
  540:         unless ($heading) { $heading=''; } else { $heading.=' '; }
  541:         $result = "\n\n".'\fbox{{\bf '.$heading.'} \qquad '."\n";
  542:     } elsif ($target eq 'edit') {
  543:         $result.=&Apache::edit::tag_start($target,$token);
  544:         $result.=&Apache::edit::text_arg('Heading:','heading',$token,70);
  545:         $result.=&Apache::edit::text_arg('Header Background:','headerbg',$token,7);
  546:         $result.=&Apache::edit::text_arg('Show text:','showtext',$token,10);
  547:         $result.=&Apache::edit::text_arg('Hide text:','hidetext',$token,10);
  548:         $result .=&Apache::edit::end_row().&Apache::edit::start_spanning_row();
  549:     } elsif ($target eq 'modified') {
  550:         my $constructtag=&Apache::edit::get_new_args($token,$parstack,
  551:                                                      $safeeval,'heading',
  552:                                                      'showtext','hidetext',
  553:                                                      'headerbg','textbg');
  554:         if ($constructtag) { $result=&Apache::edit::rebuild_tag($token); }
  555:     }
  556:     return $result;
  557: }
  558: 
  559: sub end_togglebox {
  560:   my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
  561:   my $result;
  562:   if ($target eq 'web' || $target eq 'webgrade') {
  563:     $result=&Apache::loncommon::end_togglebox();
  564:   } elsif ($target eq 'tex') {
  565:       $result = "}\n\n";
  566:   } else {
  567:       $result = '';
  568:   }
  569:   return $result;
  570: }
  571: 
  572: 
  573: 
  574: sub start_import {
  575:   my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
  576:   my $bodytext=$$parser[$#$parser]->get_text("/import");
  577:   my $result ="";
  578: 
  579:   $bodytext=&Apache::run::evaluate($bodytext,$safeeval,$$parstack[$#$parstack]);
  580: 
  581:   if ($target eq 'web' ||  $target eq 'webgrade' || $target eq 'grade' 
  582:       || $target eq 'answer' || $target eq 'tex' || $target eq 'analyze' ) {
  583:     # FIXME this probably needs to be smart about construction vs.
  584:     # non construction space.
  585:     my $location=&Apache::lonnet::filelocation($Apache::lonxml::pwd['-1'],$bodytext);
  586:     my $file=&Apache::lonnet::getfile($location);
  587:     if ($file == -1) {
  588:       &Apache::lonxml::error("<b> Unable to find <i>$bodytext as $location</i> for import</b>");
  589:       return "";
  590:     }
  591:     my $importmode=&Apache::lonxml::get_param('importmode',$parstack,$safeeval);
  592:     if (($importmode eq 'problem') || ($importmode eq 'part')) {
  593: # We are using import to import published problems
  594:        if (($importmode eq 'problem') || ($file=~/<part[^<]*>/s)) {
  595: # We explicitly don't want this to be a separate part or the problem already has parts
  596:           $file=~s/^\s*<problem>/<library>/s;
  597: 	  $file=~s/<\/problem>\s*$/<\/library>/s;
  598:        } else {
  599: # We want this to be a separate part, but it currently is not
  600:           $file=~s/^\s*<problem>/<library><part>/s;
  601: 	  $file=~s/<\/problem>\s*$/<\/part><\/library>/s;
  602:        }
  603:     }
  604:     my $dir=$location;
  605:     $dir=~s:/[^/]*$::;
  606:     #  &Apache::lonxml::debug("directory $dir $location file $file \n<b>END</b>\n");
  607:     my $id= &Apache::lonxml::get_id($parstack,$safeeval);
  608:     if (!$id) { $id=$Apache::lonxml::curdepth; }
  609:     push(@Apache::inputtags::import,$id);
  610:     push(@Apache::inputtags::importlist,$id);
  611: 
  612:     &Apache::lonxml::newparser($parser,\$file,$dir);
  613: 
  614:   } elsif ($target eq "edit" ) {
  615:     $result.=&Apache::edit::tag_start($target,$token);
  616:     my $location=$token->[1];
  617:     $location=~s/^\s*//s;
  618:     $location=~s/\s*$//s;
  619:     $result.=&Apache::edit::editline($location,$bodytext,'',40);
  620:     $result.=&Apache::edit::browse(undef,'textnode');
  621:     $result.= '&nbsp;<label>'.&mt('Import as:').
  622:               '<select name="importmode_'.$Apache::lonxml::curdepth.'">';
  623:     my %options=&Apache::lonlocal::texthash(''        => 'as standard library',
  624:                                             'problem' => 'as problem',
  625:                                             'part'    => 'as problem part(s)');
  626:     foreach my $option (sort(keys(%options))) {
  627:        $result.='<option value="'.$option.'"';
  628:        if ($option eq &Apache::lonxml::get_param('importmode',$parstack,$safeeval)) {
  629:           $result.=' selected="selected"';
  630:        }
  631:        $result.='>'.$options{$option}.'</option>';
  632:     }
  633:     $result.='</select></label>';
  634:     #FIXME this need to convert $bodytext to be a contruction space reference
  635:     #my $location=&Apache::lonnet::filelocation($Apache::lonxml::pwd['-1'],$bodytext);
  636:     #$result.="Click<a href=\"$location\">here</a> to edit<br />"
  637:   } elsif ($target eq 'modified') {
  638:       &Apache::edit::get_new_args($token,$parstack,$safeeval,'importmode');
  639:       $result='<import id="'.$token->[2]{'id'}.'" importmode="'.$token->[2]{'importmode'}.'">';
  640:       $result.=&Apache::edit::modifiedfield("/import",$parser);
  641:   } elsif ($target eq 'meta') {
  642:     my $id= &Apache::lonxml::get_id($parstack,$safeeval);
  643:     $result.='<import part="'.$Apache::inputtags::part;
  644:     if ($id) {
  645:       $result.='" id="'.$id;
  646:     }
  647:     $result.='" importmode="'.$token->[2]{'importmode'}.'">';
  648:     $result.=$bodytext;
  649:     $result.='</import>';
  650:   }
  651:   return $result;
  652: }
  653: 
  654: sub end_import {
  655:   my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
  656:   pop(@Apache::inputtags::import);
  657:   my $result;
  658:   if ($target eq 'edit' ) { $result=&Apache::edit::end_row.
  659: 				&Apache::edit::end_table(); }
  660:   return $result;
  661: }
  662: 
  663: sub start_storetc {
  664:   my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
  665:   my $result = '';
  666:   &Apache::lonxml::startredirection;
  667:   return $result; 
  668: }
  669: 
  670: sub end_storetc {
  671:     my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
  672:     my $result;
  673:     my $output=&Apache::lonxml::endredirection;
  674:     $output =~ s/\"/\&quot\;/g;
  675:     $result = '{\bf '.$output.'.}}\write\tcfile{\protect\tcpc{ '.$output.'.}{\the\value{relpage}}}';
  676:     return $result;
  677: }
  678: 
  679: 
  680: sub start_physnet {
  681:     my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
  682:     my $bodytext = '/adm/includes/physnet.sty';
  683:     my $location=&Apache::lonnet::filelocation($Apache::lonxml::pwd['-1'],$bodytext);
  684:     my $cbistyletext=&Apache::lonnet::getfile($location);
  685: 
  686:     %$style = (%$style,&Apache::style::styleparser($target,$cbistyletext));
  687:     $$parser['-1']->unget_token($token);
  688: #    if ( defined($$style{'physnet'}) ) {
  689: #        &Apache::lonxml::newparser($parser,\$$style{'physnet'});
  690: #    }
  691:     return "";
  692: }
  693: 
  694: sub end_physnet {
  695:   return '';
  696: }
  697: 
  698: sub start_standalone {
  699:   my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
  700:   my $result='';
  701:   if ($target eq 'web' || $target eq 'webgrade') {
  702:     if ( $env{'request.course.id'} ) {
  703:       my $inside = &Apache::lonxml::get_all_text("/standalone",$parser,$style);
  704:     } else {
  705:       $result='<table bgcolor="#E1E1E1" border="2"><tr><td>';
  706:     }
  707:   }
  708:   return $result;
  709: }
  710: 
  711: sub end_standalone {
  712:   my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
  713:   my $result='';
  714:   if ($target eq 'web' || $target eq 'webgrade' ) {
  715:     if ( $env{'request.course.id'} ) {
  716:     } else {
  717:       $result='</td></tr></table>';
  718:     }
  719:   }
  720:   return $result;
  721: }
  722: 
  723: sub start_comment {
  724:   my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
  725:   my $result='';
  726:   if ($target eq 'edit') {
  727:     $result=&Apache::edit::tag_start($target,$token);
  728:     my $bodytext=&Apache::lonxml::get_all_text("/comment",$parser,$style);
  729:     $result.=&Apache::edit::editfield($token->[1],$bodytext,'',80,4)
  730:   } elsif ( $target eq 'modified') {
  731:     $result=$token->[4].&Apache::edit::modifiedfield("/comment",$parser);
  732:   } elsif ( $target eq 'web'    || $target eq 'tex'  || $target eq 'grade'   ||
  733: 	    $target eq 'answer' || $target eq 'meta' || $target eq 'analyze' ||
  734: 	    $target eq 'webgrade') {
  735:     #normally throw away comments
  736:     my $bodytext=&Apache::lonxml::get_all_text("/comment",$parser,$style);
  737:   }
  738:   return $result;
  739: }
  740: 
  741: sub end_comment {
  742:   my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_;
  743:   if ($target eq 'edit' ) { return &Apache::edit::end_table(); }
  744:   return '';
  745: }
  746: 
  747: 
  748: sub xmlparse {
  749:   my ($string) = @_;
  750:   &Apache::lonxml::debug("xmlparse recursion starting with $string");
  751:   # Apache::run::evaluate does an 'eval' on the name of the subroutine
  752:   # if it detects something that looks like a subroutine, this ends up calling
  753:   # things without any arguments and since perl is nice enough to pass
  754:   # along the default arguments when you don't explicitly say no arguments
  755:   # if you call &xmlparse, it gets &xmlparse passed as it argument.
  756:   # Same thing soccurs with &chemparse.
  757:   if ($string eq '&xmlparse') { return '&xmlparse'; }
  758:   if ($string eq '&chemparse') { return '&chemparse'; }
  759:   my ($target,$token,$tagstack,$parstack,$oldparser,$safeeval,$style)=
  760:     @Apache::scripttag::parser_env;
  761:   my @parser;
  762:   &Apache::lonxml::newparser(\@parser,\$string);
  763:   &Apache::lonxml::startredirection();
  764:   my $result=&Apache::lonxml::inner_xmlparse($target,$tagstack,
  765: 					     $parstack,\@parser,
  766: 					     $safeeval,$style);
  767:   $result.=&Apache::lonxml::endredirection();
  768:   &Apache::lonxml::debug("target is $target xmlparse recursion ending with $result");
  769:   return $result;
  770: }
  771: 
  772: sub start_num {
  773:     my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style) = @_;
  774:     my $result = '';
  775:     my $inside = &Apache::lonxml::get_all_text_unbalanced("/num",$parser);
  776:     if ($target eq 'tex' || $target eq 'web' || $target eq 'webgrade') {
  777: 	$inside=&Apache::run::evaluate($inside,$safeeval,$$parstack[-1]);
  778: 	if (!$Apache::lonxml::default_homework_loaded) {
  779: 	    &Apache::lonxml::default_homework_load($safeeval);
  780: 	}
  781: 	@Apache::scripttag::parser_env = @_;
  782: 	my $format=&Apache::lonxml::get_param('format',$parstack,$safeeval);
  783: 	$result=&Apache::run::run("return &prettyprint(q\0$inside\0,q\0$format\0);",$safeeval);
  784:     }    
  785:     return $result;
  786: }
  787: 
  788: sub end_num {
  789:     my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style) = @_;
  790:     my $result = '';
  791:     return $result;
  792: }
  793: 
  794: sub start_parse {
  795:     my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style) = @_;
  796:     my $result = '';
  797:     if ( $target eq 'web'    || $target eq 'tex'    ||
  798: 	 $target eq 'grade'  || $target eq 'answer' ||
  799: 	 $target eq 'analyze'|| $target eq 'webgrade') {
  800: 	my $inside = &Apache::lonxml::get_all_text_unbalanced("/parse",$parser);
  801: 	$inside=&Apache::run::evaluate($inside,$safeeval,$$parstack[-1]);
  802: 	if (!$Apache::lonxml::default_homework_loaded) {
  803: 	    &Apache::lonxml::default_homework_load($safeeval);
  804: 	}
  805: 	@Apache::scripttag::parser_env = @_;
  806: 	$result=&Apache::run::run("return &xmlparse(q\0$inside\0);",$safeeval);
  807: 	if ($target eq 'grade' || $target eq 'answer' ||
  808: 	    $target eq 'analyze') {
  809: 	    # grade/answer/analyxe should produce no output but if we
  810: 	    # are redirecting, the redirecter should know what to do
  811: 	    # with the output
  812: 	    if (!$Apache::lonxml::redirection) { $result=''; }
  813: 	}
  814:     }
  815:     return $result;
  816: }
  817: 
  818: sub end_parse {
  819:     my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style) = @_;
  820:     my $result = '';
  821:     return $result;
  822: }
  823: 
  824: sub start_algebra {
  825:     my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style) = @_;
  826:     my $result = '';
  827:     if ( $target eq 'web'     || $target eq 'tex'    ||
  828: 	 $target eq 'grade'   || $target eq 'answer' ||
  829: 	 $target eq 'analyze' || $target eq 'webgrade') {
  830: 	my $inside = &Apache::lonxml::get_all_text_unbalanced("/algebra",$parser);
  831: 	$inside = &Apache::run::evaluate($inside,$safeeval,$$parstack[-1]);
  832: 	if ($target eq 'web' || $target eq 'tex' || $target eq 'analyze') {
  833: 	    my $style=&Apache::lonxml::get_param('style',$parstack,$safeeval);
  834: 	    $result=&Apache::lontexconvert::algebra($inside,$target,$style,$parstack,$safeeval);
  835: 	}
  836: 	$Apache::lonxml::post_evaluate=0;
  837:     }
  838:     return $result;
  839: }
  840: 
  841: sub end_algebra {
  842:     my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style) = @_;
  843:     my $result = '';
  844:     return $result;
  845: }
  846: 
  847: 1;
  848: __END__
  849: 
  850: =pod
  851: 
  852: =head1 NAME
  853: 
  854: Apache::scripttag.pm
  855: 
  856: =head1 SYNOPSIS
  857: 
  858: implements <script>, <scriptlib>, <parserlib>,
  859: and <import>
  860: 
  861: This is part of the LearningOnline Network with CAPA project
  862: described at http://www.lon-capa.org.
  863: 
  864: =cut
  865: 

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