[system] / trunk / pg / macros / AppletObjects.pl Repository:
ViewVC logotype

View of /trunk/pg/macros/AppletObjects.pl

Parent Directory Parent Directory | Revision Log Revision Log


Revision 6546 - (download) (as text) (annotate)
Sun Nov 21 15:40:38 2010 UTC (8 years, 9 months ago) by gage
File size: 15200 byte(s)
added alignedChoice.pl from the Union collection of macros
updated POD documentation.


    1 ################################################################################
    2 # WeBWorK Online Homework Delivery System
    3 # Copyright  2000-2007 The WeBWorK Project, http://openwebwork.sf.net/
    4 # $CVSHeader: pg/macros/AppletObjects.pl,v 1.24 2010/01/03 17:13:46 gage Exp $
    5 #
    6 # This program is free software; you can redistribute it and/or modify it under
    7 # the terms of either: (a) the GNU General Public License as published by the
    8 # Free Software Foundation; either version 2, or (at your option) any later
    9 # version, or (b) the "Artistic License" which comes with this package.
   10 #
   11 # This program is distributed in the hope that it will be useful, but WITHOUT
   12 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
   13 # FOR A PARTICULAR PURPOSE.  See either the GNU General Public License or the
   14 # Artistic License for more details.
   15 ################################################################################
   16 
   17 =head1 NAME
   18 
   19 AppletObjects.pl - Macro-based front end for the Applet.pm module.
   20 
   21 
   22 =head1 DESCRIPTION
   23 
   24 This subroutines in this
   25 file provide mechanisms to insert Flash applets (and  Java applets)
   26 into a WeBWorK problem.
   27 
   28 
   29 See also L<http://webwork.maa.org/pod/pg_TRUNK/lib/Applet.html>.
   30 
   31 =cut
   32 
   33 #########################################################################
   34 #
   35 # Add basic functionality to the header of the question
   36 #
   37 # don't reload this file
   38 #########################################################################
   39 
   40 sub _AppletObjects_init{
   41 
   42 main::HEADER_TEXT(<<'END_HEADER_TEXT');
   43   <script language="javascript">AC_FL_RunContent = 0;</script>
   44     <script src="/webwork2_files/applets/AC_RunActiveContent.js" language="javascript">
   45     </script>
   46     <script src="/webwork2_files/js/Base64.js" language="javascript">
   47     </script>
   48     <script src="/webwork2_files/js/ww_applet_support.js" language="javascript">
   49         //upload functions stored in /opt/webwork/webwork2/htdocs/js ...
   50     </script>
   51 END_HEADER_TEXT
   52 
   53 };
   54 
   55 =head3  FlashApplet
   56 
   57   Useage:    $applet = FlashApplet();
   58 
   59 =cut
   60 
   61 sub FlashApplet {
   62   return new FlashApplet(@_);
   63 
   64 }
   65 
   66 =head3  JavaApplet
   67 
   68   Useage:    $applet = JavaApplet(
   69 
   70 
   71   );
   72 
   73 =cut
   74 
   75 sub JavaApplet {
   76   return new JavaApplet(@_);
   77 
   78 }
   79 
   80 =head3  CanvasApplet
   81 
   82   Useage:    $applet = CanvasApplet(
   83 
   84 
   85   );
   86 
   87 =cut
   88 
   89 sub CanvasApplet {
   90   return new CanvasApplet(@_);
   91 }
   92 package Applet;
   93 
   94 
   95 
   96 =head1 Methods
   97 
   98 =cut
   99 
  100 ## this method is defined in this file
  101 ## because the main subroutines HEADER_TEXT and MODES are
  102 ## not available to the module FlashApplet when that file
  103 ## is compiled (at the time the apache child process is first initialized)
  104 
  105 =head3  insertAll
  106 
  107   Useage:   TEXT( $applet->insertAll() );
  108             \{ $applet->insertAll() \}     (used within BEGIN_TEXT/END_TEXT blocks)
  109 
  110 =cut
  111 
  112 =pod
  113 
  114 Inserts applet at this point in the HTML code.  (In TeX mode a message "Applet" is written.)  This method
  115 also adds the applets header material into the header portion of the HTML page. It effectively inserts
  116 the outputs of both C<$applet-E<gt>insertHeader> and C<$applet-E<gt>insertObject> (defined in L<Applet.pm> )
  117 in the appropriate places. In addition it creates a hidden answer blank for storing the state of the applet
  118 and provides mechanisms for revealing the state while debugging the applet.
  119 
  120 Note: This method is defined here rather than in Applet.pl because it
  121       requires access to the RECORD_FORM_LABEL subroutine
  122       and to the routine accessing the stored values of the answers.  These are defined in main::.
  123       FIXME -- with the creation of the PGcore object this can now be rewritten
  124 
  125 =cut
  126 
  127 sub insertAll {  ## inserts both header text and object text
  128   my $self = shift;
  129   my %options = @_;
  130 
  131 
  132   ##########################
  133   # determine debug mode
  134   # debugMode can be turned on by setting it to 1 in either the applet definition or at insertAll time
  135   ##########################
  136 
  137   my $debugMode = (defined($options{debug}) and $options{debug}>0) ? $options{debug} : 0;
  138   my $includeAnswerBox = (defined($options{includeAnswerBox}) and $options{includeAnswerBox}==1) ? 1 : 0;
  139   $debugMode = $debugMode || $self->debugMode;
  140     $self->debugMode( $debugMode);
  141 
  142 
  143   my $reset_button = $options{reinitialize_button} || 0;
  144   warn qq! please change  "reset_button=>1" to "reinitialize_button=>1" in the applet->installAll() command \n! if defined($options{reset_button});
  145 
  146   ##########################
  147   # Get data to be interpolated into the HTML code defined in this subroutine
  148   #
  149     # This consists of the name of the applet and the names of the routines
  150     # to get and set State of the applet (which is done every time the question page is refreshed
  151     # and to get and set Config  which is the initial configuration the applet is placed in
  152     # when the question is first viewed.  It is also the state which is returned to when the
  153     # reset button is pressed.
  154   ##########################
  155 
  156   # prepare html code for storing state
  157   my $appletName      = $self->appletName;
  158   my $appletStateName = "${appletName}_state";   # the name of the hidden "answer" blank storing state FIXME -- use persistent data instead
  159   my $getState        = $self->getStateAlias;    # names of routines for this applet
  160   my $setState        = $self->setStateAlias;
  161   my $getConfig       = $self->getConfigAlias;
  162   my $setConfig       = $self->setConfigAlias;
  163 
  164   my $base64_initialState     = encode_base64($self->initialState);
  165   main::RECORD_FORM_LABEL($appletStateName);            #this insures that the state will be saved from one invocation to the next
  166                                                         # FIXME -- with PGcore the persistant data mechanism can be used instead
  167     my $answer_value = '';
  168 
  169   ##########################
  170   # implement the sticky answer mechanism for maintaining the applet state when the question page is refreshed
  171   # This is important for guest users for whom no permanent record of answers is recorded.
  172   ##########################
  173 
  174     if ( defined( ${$main::inputs_ref}{$appletStateName} ) and ${$main::inputs_ref}{$appletStateName} =~ /\S/ ) {
  175     $answer_value = ${$main::inputs_ref}{$appletStateName};
  176   } elsif ( defined( $main::rh_sticky_answers->{$appletStateName} )  ) {
  177       warn "type of sticky answers is ", ref( $main::rh_sticky_answers->{$appletStateName} );
  178     $answer_value = shift( @{ $main::rh_sticky_answers->{$appletStateName} });
  179   }
  180   $answer_value =~ tr/\\$@`//d;   #`## make sure student answers can not be interpolated by e.g. EV3
  181   $answer_value =~ s/\s+/ /g;     ## remove excessive whitespace from student answer
  182 
  183   ##########################
  184   # insert a hidden answer blank to hold the applet's state
  185   # (debug =>1 makes it visible for debugging and provides debugging buttons)
  186   ##########################
  187 
  188 
  189   ##########################
  190   # Regularize the applet's state -- which could be in either XML format or in XML format encoded by base64
  191   # In rare cases it might be simple string -- protect against that by putting xml tags around the state
  192   # The result:
  193   # $base_64_encoded_answer_value -- a base64 encoded xml string
  194   # $decoded_answer_value         -- and xml string
  195   ##########################
  196 
  197   my $base_64_encoded_answer_value;
  198   my $decoded_answer_value;
  199   if ( $answer_value =~/<XML|<?xml/i) {
  200     $base_64_encoded_answer_value = encode_base64($answer_value);
  201     $decoded_answer_value = $answer_value;
  202   } else {
  203     $decoded_answer_value = decode_base64($answer_value);
  204     if ( $decoded_answer_value =~/<XML|<?xml/i) {  # great, we've decoded the answer to obtain an xml string
  205       $base_64_encoded_answer_value = $answer_value;
  206     } else {    #WTF??  apparently we don't have XML tags
  207       $answer_value = "<xml>$answer_value</xml>";
  208       $base_64_encoded_answer_value = encode_base64($answer_value);
  209       $decoded_answer_value = $answer_value;
  210     }
  211   }
  212   $base_64_encoded_answer_value =~ s/\r|\n//g;    # get rid of line returns
  213 
  214   ##########################
  215     # Construct answer blank for storing state -- in both regular (answer blank hidden)
  216     # and debug (answer blank displayed) modes.
  217   ##########################
  218 
  219   ##########################
  220     # debug version of the applet state answerBox and controls (all displayed)
  221     # stored in
  222     # $debug_input_element
  223   ##########################
  224 
  225 #     my $debug_input_element  = qq!\n<textarea  rows="4" cols="80"
  226 #      name = "$appletStateName" id = "$appletStateName">$decoded_answer_value</textarea><br/>!;
  227 #  conversion to base64 is now being done in the setState module
  228 #  when submitting we want everything to be in the base64 mode for safety
  229     my $debug_input_element  = qq!\n<textarea  rows="4" cols="80"
  230      name = "$appletStateName" id = "$appletStateName">$answer_value</textarea><br/>!;
  231 
  232   if ($getState=~/\S/) {   # if getStateAlias is not an empty string
  233     $debug_input_element .= qq!
  234           <input type="button"  value="$getState"
  235                  onClick=" debugText='';
  236                            ww_applet_list['$appletName'].getState() ;
  237                           if (debugText) {alert(debugText)};"
  238           />!;
  239   }
  240   if ($setState=~/\S/) {   # if setStateAlias is not an empty string
  241     $debug_input_element .= qq!
  242           <input type="button"  value="$setState"
  243                  onClick="debugText='';
  244                           ww_applet_list['$appletName'].setState();
  245                           if (debugText) {alert(debugText)};"
  246           />!;
  247   }
  248   if ($getConfig=~/\S/) {   # if getConfigAlias is not an empty string
  249     $debug_input_element .= qq!
  250           <input type="button"  value="$getConfig"
  251                  onClick="debugText='';
  252                           ww_applet_list['$appletName'].getConfig();
  253                           if (debugText) {alert(debugText)};"
  254           />!;
  255   }
  256   if ($setConfig=~/\S/) {   # if setConfigAlias is not an empty string
  257     $debug_input_element .= qq!
  258         <input type="button"  value="$setConfig"
  259                  onClick="debugText='';
  260                           ww_applet_list['$appletName'].setConfig();
  261                           if (debugText) {alert(debugText)};"
  262             />!;
  263     }
  264 
  265   ##########################
  266     # Construct answerblank for storing state
  267     # using either the debug version (defined above) or the non-debug version
  268     # where the state variable is hidden and the definition is very simple
  269     # stored in
  270     # $state_input_element
  271   ##########################
  272 
  273   my $state_input_element = ($debugMode) ? $debug_input_element :
  274         qq!\n<input type="hidden" name = "$appletStateName" id = "$appletStateName"  value ="$base_64_encoded_answer_value">!;
  275 
  276   ##########################
  277     # Construct the reset button string (this is blank if the button is not to be displayed
  278     # $reset_button_str
  279   ##########################
  280 
  281     my $reset_button_str = ($reset_button) ?
  282             qq!<input type='submit' name='previewAnswers' id ='previewAnswers' value='return this question to its initial state'
  283                  onClick="setHTMLAppletStateToRestart('$appletName')"><br/>!
  284             : ''  ;
  285 
  286   ##########################
  287   # Combine the state_input_button and the reset button into one string
  288   # $state_storage_html_code
  289   ##########################
  290 
  291 
  292     $state_storage_html_code = qq!<input type="hidden"  name="previous_$appletStateName" id = "previous_$appletStateName"  value = "$base_64_encoded_answer_value">!
  293                               . $state_input_element. $reset_button_str
  294                              ;
  295   ##########################
  296   # Construct the answerBox (if it is requested).  This is a default input box for interacting
  297   # with the applet.  It is separate from maintaining state but it often contains similar data.
  298   # Additional answer boxes or buttons can be defined but they must be explicitly connected to
  299   # the applet with additional javaScript commands.
  300   # Result: $answerBox_code
  301   ##########################
  302 
  303     my $answerBox_code ='';
  304     if ($includeAnswerBox) {
  305     if ($debugMode) {
  306 
  307       $answerBox_code = $main::BR . main::NAMED_ANS_RULE('answerBox', 50 );
  308       $answerBox_code .= qq!
  309                <br/><input type="button" value="get Answer from applet" onClick="eval(ww_applet_list['$appletName'].submitActionScript )"/>
  310                <br/>
  311               !;
  312     } else {
  313       $answerBox_code = main::NAMED_HIDDEN_ANS_RULE('answerBox', 50 );
  314     }
  315   }
  316 
  317   ##########################
  318     # insert header material
  319   ##########################
  320   main::HEADER_TEXT($self->insertHeader());
  321   # update the debug mode for this applet.
  322     main::HEADER_TEXT(qq!<script language="javascript"> ww_applet_list["$appletName"].debugMode = $debugMode;\n</script>!);
  323 
  324   ##########################
  325     # Return HTML or TeX strings to be included in the body of the page
  326   ##########################
  327 
  328     return main::MODES(TeX=>' {\bf  applet } ', HTML=>$self->insertObject.$main::BR.$state_storage_html_code.$answerBox_code);
  329 }
  330 
  331 =head3 Example problem
  332 
  333 
  334 =cut
  335 
  336 
  337 
  338 =pod
  339 
  340 
  341   DOCUMENT();
  342 
  343   # Load whatever macros you need for the problem
  344   loadMacros("PG.pl",
  345          "PGbasicmacros.pl",
  346          "PGchoicemacros.pl",
  347          "PGanswermacros.pl",
  348          "AppletObjects.pl",
  349          "MathObjects.pl",
  350          "source.pl"
  351         );
  352 
  353   ## Do NOT show partial correct answers
  354   $showPartialCorrectAnswers = 0;
  355 
  356 
  357 
  358   ###################################
  359   # Create  link to applet
  360   ###################################
  361 
  362   $applet = FlashApplet();
  363   my $appletName = "ExternalInterface";
  364   $applet->codebase(findAppletCodebase("$appletName.swf"));
  365   $applet->appletName($appletName);
  366   $applet->appletId($appletName);
  367 
  368   # findAppletCodebase looks for the applet in a list
  369   # of locations specified in global.conf
  370 
  371   ###################################
  372   # Add additional javaScript functions to header section of HTML to
  373   # communicate with the "ExternalInterface" applet.
  374   ###################################
  375 
  376   $applet->header(<<'END_HEADER');
  377   <script language="javascript" src="https://devel.webwork.rochester.edu:8002/webwork2_files/js/BrowserSniffer.js">
  378   </script>
  379 
  380 
  381   <script language="JavaScript">
  382     function getBrowser() {
  383         //alert("look for sniffer");
  384       var sniffer = new BrowserSniffer();
  385       //alert("found sniffer" +sniffer);
  386       return sniffer;
  387     }
  388 
  389     function updateStatus(sMessage) {
  390         getQE("playbackStatus").value = sMessage;
  391     }
  392 
  393     function newColor() {
  394 
  395       getApplet("ExternalInterface").updateColor(Math.round(Math.random() * 0xFFFFFF));
  396     }
  397 
  398   </script>
  399   END_HEADER
  400 
  401   ###################################
  402   # Configure applet
  403   ###################################
  404 
  405   # not used here.  Allows for uploading an xml string for the applet
  406 
  407 
  408 
  409 
  410   ###################################
  411   # write the text for the problem
  412   ###################################
  413 
  414   TEXT(beginproblem());
  415 
  416 
  417 
  418   BEGIN_TEXT
  419   \{ $applet->insertAll() \}
  420     $PAR
  421 
  422     The Flash object operates above this line.  The box and button below this line are part of
  423     the WeBWorK problem.  They communicate with the Flash object.
  424     $HR
  425     Status <input type="text" id="playbackStatus" value="started" /><br />
  426     Color <input type="button" value="new color" name="newColorButton" onClick="newColor()" />
  427      $PAR $HR
  428      This flash applet was created by Barbara Kaskosz.
  429 
  430   END_TEXT
  431 
  432   ENDDOCUMENT();
  433 
  434 
  435 
  436 
  437 =cut

aubreyja at gmail dot com
ViewVC Help
Powered by ViewVC 1.0.9