[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 5660 - (download) (as text) (annotate)
Mon May 5 16:43:29 2008 UTC (11 years, 6 months ago) by gage
File size: 14192 byte(s)
Latest reworking of the Applets.pm and AppletObjects.pl files

Debugging and error reporting should be better now.

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

aubreyja at gmail dot com
ViewVC Help
Powered by ViewVC 1.0.9