[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 5667 - (download) (as text) (annotate)
Mon May 12 00:50:24 2008 UTC (11 years, 4 months ago) by gage
File size: 14726 byte(s)
Uploading changes in the AppletObjects.pl and Applet.pm modules.

    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.9 2008/05/05 17:24: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 later Java applets)
   26 into a WeBWorK problem.
   27 
   28 
   29 =head1 SEE ALSO
   30 
   31 L<Applets.pm>.
   32 
   33 =cut
   34 
   35 #########################################################################
   36 #
   37 # Add basic functionality to the header of the question
   38 #
   39 # don't reload this file
   40 #########################################################################
   41 
   42 sub _AppletObjects_init  {
   43 
   44 
   45 main::HEADER_TEXT(<<'END_HEADER_TEXT');
   46   <script language="javascript">AC_FL_RunContent = 0;</script>
   47     <script src="/webwork2_files/applets/AC_RunActiveContent.js" language="javascript">
   48     </script>
   49     <script src="/webwork2_files/js/Base64.js" language="javascript">
   50     </script>
   51 
   52 <script language="JavaScript">
   53 
   54 //////////////////////////////////////////////////////////
   55 // applet lists
   56 //////////////////////////////////////////////////////////
   57 
   58     var  applet_initializeAction_list = new Object;  // functions for initializing question with an applet
   59     var  applet_submitAction_list     = new Object;  // functions for submitting question with applet
   60     var  applet_setState_list         = new Object;  // functions for setting state (XML) from applets
   61     var  applet_getState_list         = new Object;  // functions for getting state (XML) from applets
   62     var  applet_config_list           = new Object;  // functions for  configuring on applets
   63   var  applet_checkLoaded_list      = new Object;  // functions for probing the applet to see if it is loaded
   64   var  applet_reportsLoaded_list    = new Object;  // flag set by applet
   65   var  applet_isReady_list          = new Object;  // flag set by javaScript in checkLoaded
   66 
   67 //////////////////////////////////////////////////////////
   68 // DEBUGGING tools
   69 //////////////////////////////////////////////////////////
   70   var debug;
   71   var debugText = "";
   72   function set_debug(num) { // setting debug for any applet sets it for all of them
   73     if (num) {
   74       debug =1;
   75     }
   76   }
   77   function debug_add(str) {
   78     if (debug) {
   79       debugText = debugText + "\n\n" +str;
   80     }
   81   }
   82 
   83 //////////////////////////////////////////////////////////
   84 // INITIALIZE and SUBMIT actions
   85 //////////////////////////////////////////////////////////
   86 
   87     function submitAction()  {
   88         alert("Begin submitAction!!!!!");
   89         if (debug) {debugText = "Begin looping through applet_submitAction_list\n";}
   90     for (var applet in applet_submitAction_list)  {
   91        //alert(applet);
   92        applet_submitAction_list[applet]();
   93     }
   94     if (debug) {alert(debugText); debugText="";};
   95       return(1);
   96     }
   97     function initializeAction() {
   98         var iMax = 10;
   99         debugText="start intializeAction() with up to " +iMax + " attempts\n";
  100       for (var appletName in applet_initializeAction_list)  {
  101       safe_applet_initialize(appletName, iMax);
  102       }
  103 
  104     }
  105 
  106     // applet can set isReady flag by calling applet_loaded(appletName, loaded);
  107     function applet_loaded(appletName,loaded) {
  108         applet_reportsLoaded_list[appletName] = loaded; // 0 means not loaded
  109       debug_add("applet reporting that it has been loaded = " + loaded );
  110     }
  111 
  112     // insures that applet is loaded before initializing it
  113   function safe_applet_initialize(appletName, i) {
  114     debug_add("Iteration " + i + " of safe_applet_initialize with applet " + appletName );
  115 
  116     i--;
  117     var applet_loaded = applet_checkLoaded_list[appletName]();
  118     debug_add("applet is ready = " + applet_loaded  );
  119 
  120     if ( 0 < i && !applet_loaded ) { // wait until applet is loaded
  121       debug_add("applet " + appletName + "not ready try again");
  122       window.setTimeout( "safe_applet_initialize(\"" + appletName + "\"," + i +  ")",1);
  123     } else if( 0 < i ){  // now that applet is loaded configure it and initialize it with saved data.
  124       debug_add(" Ready to initialize applet " + appletName + " with " + i +  " iterations left. ");
  125 
  126       // in-line handler -- configure and initialize
  127       try{
  128         if (debug && typeof(getApplet(appletName).debug) == "function" ) {
  129           getApplet(appletName).debug(1);  // turn the applet's debug functions on.
  130         }
  131       } catch(e) {
  132         alert("Unable to set debug mode for applet " + appletName);
  133       }
  134       try{
  135         applet_config_list[appletName]();
  136       } catch(e) {
  137         alert("Unable to configure " + appletName + " \n " +e );
  138       }
  139       try{
  140         applet_initializeAction_list[appletName]();
  141       } catch(e) {
  142         alert("unable to initialize " + appletName + " \n " +e );
  143       }
  144 
  145     } else {
  146       if (debug) {alert("Error: timed out waiting for applet " +appletName + " to load");}
  147     }
  148     if (debug) {alert(debugText); debugText="";};
  149   }
  150 
  151 ///////////////////////////////////////////////////////
  152 // Utility functions
  153 ///////////////////////////////////////////////////////
  154 
  155 
  156   function getApplet(appletName) {
  157       var isIE = navigator.appName.indexOf("Microsoft") != -1;
  158       var obj = (isIE) ? window[appletName] : window.document[appletName];
  159       //return window.document[appletName];
  160       if (obj && (obj.name = appletName)) {
  161         return( obj );
  162       } else {
  163        // alert ("can't find applet " + appletName);
  164       }
  165    }
  166 
  167   function listQuestionElements() { // list all HTML input and textarea elements in main problem form
  168      var isIE = navigator.appName.indexOf("Microsoft") != -1;
  169      var elementList = (isIE) ?  document.getElementsByTagName("input") : document.problemMainForm.getElementsByTagName("input");
  170      var str=elementList.length +" Question Elements\n type | name = value  < id > \n";
  171      for( var i=0; i< elementList.length; i++) {
  172        str = str + " "+i+" " + elementList[i].type
  173                + " | " + elementList[i].name
  174                + "= " + elementList[i].value +
  175                " <" + elementList[i].id + ">\n";
  176      }
  177      elementList = (isIE) ?  document.getElementsByTagName("textarea") : document.problemMainForm.getElementsByTagName("textarea");
  178      for( var i=0; i< elementList.length; i++) {
  179        str = str + " "+i+" " + elementList[i].type
  180                + " | " + elementList[i].name
  181                + "= " + elementList[i].value +
  182                " <" + elementList[i].id + ">\n";
  183      }
  184      alert(str +"\n Place listQuestionElements() at end of document in order to get all form elements!");
  185   }
  186 
  187   function base64Q(str) {
  188     return ( !str.match(/<XML/i) && !str.match(/<?xml/i));
  189   }
  190   function setEmptyState(appletName){
  191     var newState = "<xml></xml>";
  192     applet_setState_list[appletName](newState);
  193     var applet = getApplet(appletName);
  194     getQE(appletName+"_state").value = newState;
  195     getQE("previous_" + appletName + "_state").value = newState
  196   }
  197 
  198   function getQE(name1) { // get Question Element in problemMainForm by name
  199     var isIE = navigator.appName.indexOf("Microsoft") != -1;
  200     var obj = (isIE) ? document.getElementById(name1)
  201               :document.problemMainForm[name1];
  202     // needed for IE -- searches id and name space so it can be unreliable if names are not unique
  203     if (!obj || obj.name != name1) {
  204       alert("Can't find element " + name1);
  205       listQuestionElements();
  206     } else {
  207       return( obj );
  208     }
  209 
  210   }
  211   function getQuestionElement(name1) {
  212     return getQE(name1);
  213   }
  214 
  215  </script>
  216 
  217 END_HEADER_TEXT
  218 
  219 };
  220 
  221 =head3
  222   FlashApplet
  223 
  224   Useage:    $applet = FlashApplet();
  225 
  226 =cut
  227 
  228 sub FlashApplet {
  229   return new FlashApplet(@_);
  230 
  231 }
  232 
  233 sub JavaApplet {
  234   return new JavaApplet(@_);
  235 
  236 }
  237 
  238 package Applet;
  239 
  240 
  241 
  242 =head2 Methods
  243 
  244 =cut
  245 
  246 ## this method is defined in this file
  247 ## because the main subroutines HEADER_TEXT and MODES are
  248 ## not available to the module FlashApplet when that file
  249 ## is compiled (at the time the apache child process is first initialized)
  250 
  251 =head3  insertAll
  252 
  253   Useage:   TEXT( $applet->insertAll() );
  254             \{ $applet->insertAll() \}     (used within BEGIN_TEXT/END_TEXT blocks)
  255 
  256 =cut
  257 
  258 =pod
  259 
  260 Inserts applet at this point in the HTML code.  (In TeX mode a message "Applet" is written.)  This method
  261 also adds the applets header material into the header portion of the HTML page. It effectively inserts
  262 the outputs of both C<$applet-E<gt>insertHeader> and C<$applet-E<gt>insertObject> (defined in L<Applet.pm> )
  263 in the appropriate places.
  264 
  265 Note: This method is defined here rather than in Applet.pl because it
  266       requires access to the RECORD_FORM_LABEL subroutine
  267       and to the routine accessing the stored values of the answers.  These are defined in main::.
  268 
  269 =cut
  270 
  271 sub insertAll {  ## inserts both header text and object text
  272   my $self = shift;
  273   my %options = @_;
  274   $self->debug( (defined($options{debug}) and $options{debug}==1) ? 1 : 0 );
  275   my $reset_button = $options{reset_button} || 0;
  276   # prepare html code for storing state
  277   my $appletName      = $self->appletName;
  278   my $appletStateName = "${appletName}_state";
  279   my $getState        = $self->getStateAlias;
  280   my $setState        = $self->setStateAlias;
  281   my $base64_initialState     = $self->base64_state;
  282   main::RECORD_FORM_LABEL($appletStateName);            #this insures that they'll be saved from one invocation to the next
  283   #main::RECORD_FORM_LABEL("previous_$appletStateName");
  284     my $answer_value = '';
  285   $answer_value = ${$main::inputs_ref}{$appletStateName} if defined(${$main::inputs_ref}{$appletStateName});
  286 
  287   if ( defined( $main::rh_sticky_answers->{$appletStateName} ) ) {
  288     $answer_value = shift( @{ $main::rh_sticky_answers->{$appletStateName} });
  289     $answer_value = '' unless defined($answer_value);
  290   }
  291   $answer_value =~ tr/\\$@`//d;   #`## make sure student answers can not be interpolated by e.g. EV3
  292   $answer_value =~ s/\s+/ /g;     ## remove excessive whitespace from student answer
  293 
  294   #######
  295   # insert a hidden variable to hold the applet's state (debug =>1 makes it visible for debugging and provides debugging buttons)
  296   #######
  297   my $base_64_encoded_answer_value = ($answer_value =~/<XML|<?xml/i)? encode_base64($answer_value) : $answer_value;
  298   my $decoded_answer_value         = ($answer_value =~/<XML|<?xml/i) ? $answer_value : decode_base64($answer_value);
  299     my $debug_input_element  = qq!\n<textarea  rows="4" cols="80"
  300      name = "$appletStateName">$decoded_answer_value</textarea><br/>
  301           <input type="button"  value="$getState"
  302                  onClick="applet_getState_list['$appletName']()"
  303           >
  304           <input type="button"  value="$setState"
  305                  onClick="var tmp = getQE('$appletStateName').value;
  306                           applet_setState_list['$appletName'](tmp);"
  307           >
  308     !;
  309   my $state_input_element = ($self->debug == 1) ? $debug_input_element :
  310         qq!\n<input type="hidden" name = "$appletStateName" value ="$base_64_encoded_answer_value">!;
  311     my $reset_button_str = ($reset_button) ?
  312             qq!<br/><input type='button' value='set applet state empty' onClick="setEmptyState('$appletName')">
  313                     <input type="button" value="reinitialize applet" onClick="getQE('$appletStateName').value='$base64_initialState'"/>!
  314             : ''
  315     ;
  316   # always base64 encode the hidden answer value to prevent problems with quotes.
  317     #
  318   $state_storage_html_code =
  319                       $reset_button_str.
  320                       $state_input_element.
  321                         qq!<input type="hidden"  name="previous_$appletStateName" value = "$base_64_encoded_answer_value">!;
  322     #######
  323     # insert header material
  324     #######
  325   main::HEADER_TEXT($self->insertHeader());
  326     return main::MODES(TeX=>' {\bf  applet } ', HTML=>$self->insertObject.$main::BR.$state_storage_html_code);
  327 }
  328 
  329 =head3 Example problem
  330 
  331 
  332 =cut
  333 
  334 
  335 
  336 =pod
  337 
  338 
  339   DOCUMENT();
  340 
  341   # Load whatever macros you need for the problem
  342   loadMacros("PG.pl",
  343          "PGbasicmacros.pl",
  344          "PGchoicemacros.pl",
  345          "PGanswermacros.pl",
  346          "AppletObjects.pl",
  347          "MathObjects.pl",
  348          "source.pl"
  349         );
  350 
  351   ## Do NOT show partial correct answers
  352   $showPartialCorrectAnswers = 0;
  353 
  354 
  355 
  356   ###################################
  357   # Create  link to applet
  358   ###################################
  359 
  360   $applet = FlashApplet();
  361   my $appletName = "ExternalInterface";
  362   $applet->codebase(findAppletCodebase("$appletName.swf"));
  363   $applet->appletName($appletName);
  364   $applet->appletId($appletName);
  365 
  366   # findAppletCodebase looks for the applet in a list
  367   # of locations specified in global.conf
  368 
  369   ###################################
  370   # Add additional javaScript functions to header section of HTML to
  371   # communicate with the "ExternalInterface" applet.
  372   ###################################
  373 
  374   $applet->header(<<'END_HEADER');
  375   <script type="text/javascript" src="https://devel.webwork.rochester.edu:8002/webwork2_files/js/BrowserSniffer.js">
  376   </script>
  377 
  378 
  379   <script language="JavaScript">
  380     function getBrowser() {
  381         //alert("look for sniffer");
  382       var sniffer = new BrowserSniffer();
  383       //alert("found sniffer" +sniffer);
  384       return sniffer;
  385     }
  386 
  387     function updateStatus(sMessage) {
  388         getQE("playbackStatus").value = sMessage;
  389     }
  390 
  391     function newColor() {
  392 
  393       getApplet("ExternalInterface").updateColor(Math.round(Math.random() * 0xFFFFFF));
  394     }
  395 
  396   </script>
  397   END_HEADER
  398 
  399   ###################################
  400   # Configure applet
  401   ###################################
  402 
  403   # not used here.  Allows for uploading an xml string for the applet
  404 
  405 
  406 
  407 
  408   ###################################
  409   # write the text for the problem
  410   ###################################
  411 
  412   TEXT(beginproblem());
  413 
  414 
  415 
  416   BEGIN_TEXT
  417   \{ $applet->insertAll() \}
  418     $PAR
  419 
  420     The Flash object operates above this line.  The box and button below this line are part of
  421     the WeBWorK problem.  They communicate with the Flash object.
  422     $HR
  423     Status <input type="text" id="playbackStatus" value="started" /><br />
  424     Color <input type="button" value="new color" name="newColorButton" onClick="newColor()" />
  425      $PAR $HR
  426      This flash applet was created by Barbara Kaskosz.
  427 
  428   END_TEXT
  429 
  430   ENDDOCUMENT();
  431 
  432 
  433 
  434 
  435 =cut

aubreyja at gmail dot com
ViewVC Help
Powered by ViewVC 1.0.9