[system] / trunk / pg / lib / Applet.pm Repository:
ViewVC logotype

View of /trunk/pg/lib/Applet.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 6026 - (download) (as text) (annotate)
Sun Mar 15 19:25:03 2009 UTC (10 years, 8 months ago) by gage
File size: 34214 byte(s)
Added documentation for applet API

added initialState to the instance variables

    1 ################################################################################
    2 # WeBWorK Online Homework Delivery System
    3 # Copyright  2000-2007 The WeBWorK Project, http://openwebwork.sf.net/
    4 # $CVSHeader: pg/lib/Applet.pm,v 1.20 2009/03/10 20:58: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 Applet.pl - Provides code for inserting FlashApplets and JavaApplets into webwork problems
   20 
   21 =head1 SYNPOSIS
   22 
   23   ###################################
   24   # Create  link to applet
   25   ###################################
   26  $appletName = "PointGraph";
   27 $applet =  FlashApplet(
   28    codebase              => findAppletCodebase("$appletName.swf"),
   29    appletName            => $appletName,
   30    appletId              => $appletName,
   31    setStateAlias         => 'setXML',
   32    getStateAlias         => 'getXML',
   33    setConfigAlias        => 'config',
   34    answerBoxAlias        => 'receivedField',
   35 );
   36 
   37 ###################################
   38 # Configure applet
   39 ###################################
   40 
   41 #data to set up the equation
   42 $applet->config(qq{<XML expr='(x - $a)^3 + $b/$a * x' />});
   43 # initial points
   44 $applet->state(qq{<XML>
   45 </XML>});
   46 ###################################
   47 #insert applet into body
   48 ###################################
   49 
   50 TEXT( MODES(TeX=>'object code', HTML=>$applet->insertAll(
   51  debug=>0,
   52  reset_button=>1,
   53  )));
   54 
   55 
   56 =head1 DESCRIPTION
   57 
   58 This file provides an object to store in one place
   59 all of the information needed to call an applet.
   60 
   61 The object FlashApplet has defaults for inserting flash applets.
   62 
   63 =over
   64 
   65 =item *
   66 
   67 =item *
   68 
   69 =back
   70 
   71 (not yet completed)
   72 
   73 The module JavaApplet has defaults for inserting java applets.
   74 
   75 The module Applet stores common code for the two types of applet.
   76 
   77 =head1 USAGE
   78 
   79 These modules are activate by listing it in the modules section of global.conf and rebooting the server.
   80 The companion file to this one is macros/AppletObjects.pl
   81 
   82 qw(Applet FlashApplet JavaApplet)
   83 
   84 =cut
   85 
   86 
   87 
   88 package Applet;
   89 
   90 use URI::Escape;
   91 
   92 
   93 
   94 use MIME::Base64 qw( encode_base64 decode_base64);
   95 
   96 
   97 =head2 Default javaScript functions placed in header
   98 
   99 =pod
  100 
  101 These functions are automatically defined for use for
  102 any javaScript placed in the text of a PG question.
  103 
  104     getApplet(appletName)  -- finds the applet path in the DOM
  105 
  106     submitAction()            -- calls the submit action of the applets
  107 
  108     initializeWWquestion()    -- calls the initialize action of the applets
  109 
  110     getQE(name)               -- gets an HTML element of the question by name
  111                                  or by id.  Be sure to keep all names and ids
  112                                  unique within a given PG question.
  113 
  114     getQuestionElement(name)  -- long form of getQE(name)
  115 
  116     listQuestionElements()    -- for discovering the names of inputs in the
  117                                  PG question.  An alert dialog will list all
  118                                  of the elements.
  119       Usage: Place this at the END of the question, just before END_DOCUMENT():
  120 
  121                 TEXT(qq!<script> listQuestionElements() </script>!);
  122                 ENDDOCUMENT();
  123              to obtain a list of all of the HTML elements in the question
  124 
  125     ----------------------------------------------------------------------------
  126 
  127 
  128     List of  accessor methods made available by the FlashApplet class:
  129         Usage:  $current_value = $applet->method(new_value or empty)
  130         These can also be set when creating the class -- for exampe:
  131              $applet = new FlashApplet(
  132                        # can be replaced by $applet =FlashApplet() when using AppletObjects.pl
  133                        codebase   => findAppletCodebase("$appletName.swf"),
  134                        appletName => $appletName,
  135                        appletId   => $appletName,
  136                        submitActionAlias => 'checkAnswer',
  137             );
  138 
  139 
  140         appletId         for simplicity and reliability appletId and appletName are always the same
  141         appletName
  142         archive      the name of the .jar file containing the applet code
  143         code         the name of the applet code in the .jar archive
  144         codebase     a prefix url used to find the archive and the applet itself
  145 
  146         height       rectangle alloted in the html page for displaying the applet
  147 
  148         params       an anonymous array containing name/value pairs
  149                      to configure the applet [name =>'value, ...]
  150 
  151         header       stores the text to be added to the header section of the html page
  152         object       stores the text which places the applet on the html page
  153 
  154         debug        in debug mode several alerts mark progress through the procedure of calling the applet
  155 
  156         config       configuration are those customizable attributes of the applet which don't
  157                      change as it is used.  When stored in hidden answer fields
  158                      it is usually stored in base64 encoded format.
  159         base64_config base64 encode version of the contents of config
  160 
  161         configAlias  (default: setConfig ) names the applet command called with the contents of $self->config
  162                      to configure the applet.  The parameters are passed to the applet in plain text using <xml>
  163                      The outer tags must be   <xml> .....   </xml>
  164         setConfigAlias (default: setConfig) -- a synonym for configAlias
  165         getConfigAlias (default: getConfig) -- retrieves the configuration from the applet.  This is used
  166                      mainly for debugging.  In principal the configuration remains the same for a given instance
  167                      of the applet -- i.e. for the homework question for a single student.  The state however
  168                      will change depending on the interactions between the student and the applet.
  169         initialState  the state consists of those customizable attributes of the applet which change
  170                      as the applet is used by the student.  It is stored by the calling .pg question so that
  171                      when revisiting the question the applet will be restored to the same state it was left in when the question was last
  172                      viewed.
  173 
  174         getStateAlias  (default: getState) alias for command called to read the current state of the applet.
  175                        The state is passed in plain text xml format with outer tags: <xml>....</xml>
  176         setStateAlias  (default: setState) alias for the command called to reset the  state of the applet.
  177                        The state is passed in plain text in xml format with outer tags: <xml>....</xml>
  178 
  179         base64_state   returns the base64 encoded version of the state stored in the applet object.
  180 
  181         initializeActionAlias  -- (default: initializeAction) the name of the javaScript subroutine called to initialize the applet (some overlap with config/ and setState
  182         submitActionAlias      -- (default: submitAction)the name of the javaScript subroutine called when the submit button of the
  183                                   .pg question is pressed.
  184         answerBoxAlias         -- name of answer box to return answer to: default defaultAnswerBox
  185         getAnswer              -- (formerly sendData) get student answer from applet and place in answerBox
  186         returnFieldName        -- (deprecated) synonmym for answerBoxAlias
  187 
  188 
  189 =cut
  190 
  191 =head4 More details
  192 
  193 There are three different "images" of the applet.  The first is the java or flash applet itself.  The object that actually does the work.
  194 The second is a perl image of the applet -- henceforth the perlApplet -- which is configured in the .pg file and allows a WeBWorK question
  195 to communicate with the applet.  The third image is a javaScript image of the applet -- henceforth the jsApplet which is a mirror of the perlApplet
  196 but is available to the javaScript code setup and executed in the virtual HTML page defined by the .pg file of the WeBWorK question. One can think of
  197 the jsApplet as a runtime version of the perlApplet since it can be accessed and modified after the virtual HTML page has been created by
  198 the PG rendering process.
  199 
  200 The perlApplet is initialized by   $newApplet = new flashApplet( appletName=>'myApplet',..... ); The jsApplet is automatically defined in
  201 ww_applet_list["myApplet"] by copying the instance variables of $newApplet to a corresponding javaScript object.  So  $newApplet->{appletName}
  202 corresponds to ww_applet_list["myApplet"].appletName.  (This paragraph is not yet fully implemented :-().
  203 
  204 Currently all messages read by the applet are xml text.  If some of the code needs to be printed in the HTML header than it is converted
  205 to a base64 constant and then converted back to text form when it is read by a javaScript subroutine.
  206 
  207 The perlApplet has  methods that help place the jsApplet code on the HTML page and create the link to the applet itself.
  208 In particular instance variables such as "setStateAlias", "getStateAlias" connect the WW default of "setState" to subroutine
  209 name chosen by the applet designer.  The aim is to make it easier to connect to applets previously designed to work
  210 with javaScript in an HTML page or other  systems.
  211 
  212 
  213 The jsApplet acts as an intermediary for commands directed at the applet.
  214 It is not necessary for the minimal operations of
  215 configuring the applet and maintaining
  216 state from one viewing of the WW question to address the applet directly.
  217 The methods such as "setState", "getState", "setConfig" which are part of the jsApplet
  218 take care of the book keeping details.
  219 It is also possible to make direct calls to the applet from handcrafted javaScript subroutines,
  220 but it may be convenient to store these as additional methods in the
  221 jsApplet.
  222 
  223 =cut
  224 
  225 =head4 Detecting that the applet is ready
  226 
  227 Timing issues are among the pitfalls awaiting when using flash or java applets in WW questions.  It is important that the WW question
  228 does not issue any commands to the applet until the applet is fully loaded, including the uploading of any additional configuration
  229 information from XML files.  This can be tricky since the timing issues usually don't arise when initiating the applet from an HTML page.
  230 
  231 The WW API performs the following actions to determine if the applet is loaded:
  232 
  233   check the ww_applet_list[appletName].isReady flag (1== applet is ready)
  234                       -- this caches the readiness information so that it doesn't
  235                          have to be repeated within a given viewing of a WW question
  236                          If this is 1 then the applet is ready.
  237   determine whether the applet's isActive subroutine is defined AND returns 1 when called.
  238                       -- if the return value is 1 the applet is ready, if it is zero or no response then the applet is NOT ready
  239                       -- If the applet has an isActive() subroutine -- there is no alias for this --
  240                          then it must return 1 as soon as the applet is ready.  Otherwise
  241                          the applet will timeout.
  242   determine whether the applet's setConfig subroutine is defined.
  243                       -- applet.{setConfigAlias}.
  244   determine whether the applet's setState subroutine is defined.
  245   determine whether the  jsApplets ww_applet_list[appletName].reportsLoaded flag is set to 1
  246                       -- this can be set by the applet if it calls the javaScript function
  247                          "applet_loaded(appletName, loaded_status).  The loaded_status is 1 or 0
  248 
  249   Logic for determining applet status: if any one of the above checks succeeds (or returns 1) then the applet is
  250                         consdered to be ready  UNLESS the isActive() exists and the call returns a 0 or no response. In this case
  251                         the applet is assumed to be loading additional data and is not yet ready.
  252 
  253                         For this reason if the isActive subroutine
  254                         is defined in the applet it must return a 1 once the applet is prepared to accept additional commands.
  255                         (Since there are some extent flashApplets with non-functioning isActive() subroutines a temporary workaround
  256                          assuems that after C<maxInitializationAttempts> -- 5 by default -- the applet is in fact ready but the
  257                          isActive() subroutine is non functioning.  This can give rise to false "readiness" signals if the applet
  258                          takes a long time to load auxiliary files.)
  259 
  260 The applet itself can take measures to insure that the setConfig subroutine is prepared to respond immediately once the applet is loaded.
  261 It can include timers that delay execution of the configuring actions until all of the auxiliary files needed by the applet are loaded.
  262 
  263 
  264 =cut
  265 
  266 
  267 =head4 Initialization sequence
  268 
  269 When the WW question is loaded the C<initializeWWquestion> javaScript subroutine calls each of the applets used in the question asking them
  270 to initialize themselves.
  271 
  272 The applets initialization method is as follows:
  273 
  274                        -- wait until the applet is loaded and the applet has loaded all of its auxiliary files.
  275                        -- set the debugMode in the applet
  276                        -- call the setConfig  method in the javaScript applet  -- (configuration parameters are "permanent" for the life of the applet
  277                        -- call the setInitialization method in the javaScript applet -- this often calls the setState method in the applet
  278 
  279 =cut
  280 
  281 =head Methods defined for the javaScript applet   ww_applet_list[appletName]
  282 
  283 This is not a comprehensive list
  284 
  285   setConfig         -- transmits the information for configuring the applet
  286 
  287   getConfig         -- retrieves the configuration information -- this is used mainly for debugging and may not be defined in most applets
  288 
  289 
  290   setState          -- sets the current state (1) from the appletName_state HTML element if this contains an <xml>...</xml> string
  291                     -- if the value contains <xml>restart_applet</xml> then set the current state to ww_applet_list[appletName].initialState
  292                     -- if the value is a blank string set the current state to ww_applet_list[appletName].initialState
  293 
  294 
  295   getState          -- retrieves the current state and stores in the appletName_state HTML element.
  296 
  297 
  298 
  299 
  300 
  301 
  302 
  303 =head Submit sequence
  304 
  305 When the WW question submit button is pressed the form containing the WW question calles the javaScript "submitAction()" which then asks
  306 each of the applets on the page to perform its submit action which consists of
  307 
  308   -- if the applet is to be reinitialized (appletName_state contains <xml>restart_applet</xml>) then
  309      the HTML elements appletName_state and previous_appletName_state are set to <xml>restart_applet</xml>
  310      to be interpreted by the next setState command
  311   -- Otherwise getState() from the applet and save it to the  HTML input element appletName_state
  312   -- Perform the javaScript commands in .submitActionScript (default: '' )
  313      a typical submitActionScript looks like getQE(this.answerBox).value = getApplet(appletName).getAnswer()  )
  314 
  315 =head4 Requirements for applets
  316 
  317 The following methods are desirable in an applet that preserves state in a WW question.  None of them are required.
  318 
  319   setState(str)   (default: setXML)
  320                      -- set the current state of the applet from an xml string
  321                      -- should be able to accept an empty string or a string of
  322                         the form <XML>.....</XML> without creating errors
  323                      -- can be designed to receive other forms of input if it is
  324                         coordinated with the WW question.
  325   getState()      (default: getXML)
  326                    -- return the current state of the applet in an xml string.
  327                      -- an empty string or a string of the form <XML>.....</XML>
  328                         are the standard responses.
  329                      -- can be designed to return other strings if it is
  330                         coordinated with the WW question.
  331   setConfig(str) (default: setConfig)
  332                      -- If the applet allows configuration this configures the applet
  333                         from an xml string
  334                        -- should be able to accept an empty string or a string of the
  335                           form <XML>.....</XML> without creating errors
  336                      -- can be designed to receive other forms of input if it is
  337                         coordinated with the WW question.
  338     getConfig      (default: getConfig)
  339                      -- This returns a string defining the configuration of the
  340                         applet in an xml string
  341                        -- an empty string or a string of the form <XML>.....</XML>
  342                           are the standard responses.
  343                      -- can be designed to return other strings if it is
  344                         coordinated with the WW question.
  345                      -- this method is used for debugging to ensure that
  346                         the configuration was set as expected.
  347   getAnswer      (default: getAnswer)
  348                      -- Returns a string (usually NOT xml) which is the
  349                         response that the student is effectvely submitting to answer
  350                         the WW question.
  351 
  352 
  353 =cut
  354 
  355 sub new {
  356    my $class = shift;
  357    my $self = {
  358     appletName =>'',
  359     code=>'',
  360     codebase=>'',
  361 #   appletId  =>'',   #always use identical applet Id's and applet Names
  362     params    =>undef,
  363     width     => 550,
  364     height    => 400,
  365     bgcolor   => "#869ca7",
  366     base64_state       =>  undef,     # this is a state to use for initializing the first occurence of the question.
  367     base64_config      =>  undef,     # this is the initial (and final?) configuration
  368 #   configuration      => '',         # configuration defining the applet
  369     initialState       => '',         # initial state.  (I'm considering storing everything as ascii and converting on the fly to base64 when needed.)
  370     getStateAlias      =>  'getXML',
  371     setStateAlias      =>  'setXML',
  372     configAlias        =>  '',        # deprecated
  373     getConfigAlias     =>  'getConfig',
  374     setConfigAlias     =>  'setConfig',
  375     initializeActionAlias => 'setXML',
  376     maxInitializationAttempts => 5,   # number of attempts to initialize applet
  377     submitActionAlias  =>  'getXML',
  378     submitActionScript  => '',        # script executed on submitting the WW question
  379     answerBoxAlias     =>  'answerBox',
  380     answerBox          =>  '',        # deprecated
  381     returnFieldName    => '',         # deprecated
  382     headerText         =>  DEFAULT_HEADER_TEXT(),
  383     objectText         => '',
  384     debugMode          => 0,
  385     @_,
  386   };
  387   bless $self, $class;
  388   $self->initialState('<xml></xml>');
  389   if ($self->{returnFieldName} or $self->{answerBox} ) { # backward compatibility
  390     warn "use answerBoxAlias instead of returnFieldName or answerBox";
  391     $self->{answerBox}='';
  392     $self->{returnFieldName}='';
  393   }
  394   if ($self->{configAlias}) { # backward compatibility
  395     warn "use setConfigAlias instead of configAlias";
  396     $self->{configAlias}='';
  397   }
  398   $self->config('<xml></xml>');
  399   return $self;
  400 }
  401 
  402 sub  header {
  403   my $self = shift;
  404   if ($_[0] eq "reset") {  # $applet->header('reset');  erases default header text.
  405     $self->{headerText}='';
  406   } else {
  407     $self->{headerText} .= join("",@_);  # $applet->header(new_text); concatenates new_text to existing header.
  408   }
  409     $self->{headerText};
  410 }
  411 sub  object {
  412   my $self = shift;
  413   if ($_[0] eq "reset") {
  414     $self->{objectText}='';
  415   } else {
  416     $self->{objectText} .= join("",@_);
  417   }
  418     $self->{objectText};
  419 }
  420 sub params {
  421   my $self = shift;
  422   if (ref($_[0]) =~/HASH/) {
  423     $self->{params} = shift;
  424   } elsif ( !defined($_[0]) or $_[0] =~ '') {
  425     # do nothing (read)
  426   } else {
  427     warn "You must enter a reference to a hash for the parameter list";
  428   }
  429   $self->{params};
  430 }
  431 
  432 sub initializeActionAlias {
  433   my $self = shift;
  434   $self->{initializeActionAlias} = shift ||$self->{initializeActionAlias}; # replace the current contents if non-empty
  435     $self->{initializeActionAlias};
  436 }
  437 
  438 sub submitActionAlias {
  439   my $self = shift;
  440   $self->{submitActionAlias} = shift ||$self->{submitActionAlias}; # replace the current contents if non-empty
  441     $self->{submitActionAlias};
  442 }
  443 sub submitActionScript {
  444   my $self = shift;
  445   $self->{submitActionScript} = shift ||$self->{submitActionScript}; # replace the current contents if non-empty
  446     $self->{submitActionScript};
  447 }
  448 sub getStateAlias {
  449   my $self = shift;
  450   $self->{getStateAlias} = shift ||$self->{getStateAlias}; # replace the current contents if non-empty
  451     $self->{getStateAlias};
  452 }
  453 
  454 sub setStateAlias {
  455   my $self = shift;
  456   $self->{setStateAlias} = shift ||$self->{setStateAlias}; # replace the current contents if non-empty
  457     $self->{setStateAlias};
  458 }
  459 sub configAlias {
  460   my $self = shift;
  461   $self->{setConfigAlias} = shift ||$self->{setConfigAlias}; # replace the current contents if non-empty
  462     $self->{setConfigAlias};
  463 }
  464 sub setConfigAlias {
  465   my $self = shift;
  466   $self->{setConfigAlias} = shift ||$self->{setConfigAlias}; # replace the current contents if non-empty
  467     $self->{setConfigAlias};
  468 }
  469 sub getConfigAlias {
  470   my $self = shift;
  471   $self->{getConfigAlias} = shift ||$self->{getConfigAlias}; # replace the current contents if non-empty
  472     $self->{getConfigAlias};
  473 }
  474 
  475 sub answerBoxName {
  476   my $self = shift;
  477   $self->{answerBox} = shift ||$self->{answerBox}; # replace the current contents if non-empty
  478     $self->{answerBox};
  479 }
  480 sub codebase {
  481   my $self = shift;
  482   $self->{codebase} = shift ||$self->{codebase}; # replace the current codebase if non-empty
  483     $self->{codebase};
  484 }
  485 sub code {
  486   my $self = shift;
  487   $self->{code} = shift ||$self->{code}; # replace the current code if non-empty
  488     $self->{code};
  489 }
  490 sub height {
  491   my $self = shift;
  492   $self->{height} = shift ||$self->{height}; # replace the current height if non-empty
  493     $self->{height};
  494 }
  495 sub width {
  496   my $self = shift;
  497   $self->{width} = shift ||$self->{width}; # replace the current width if non-empty
  498     $self->{width};
  499 }
  500 sub bgcolor {
  501   my $self = shift;
  502   $self->{bgcolor} = shift ||$self->{bgcolor}; # replace the current background color if non-empty
  503     $self->{bgcolor};
  504 }
  505 sub archive {
  506   my $self = shift;
  507   $self->{archive} = shift ||$self->{archive}; # replace the current archive if non-empty
  508     $self->{archive};
  509 }
  510 sub appletName {
  511   my $self = shift;
  512   $self->{appletName} = shift ||$self->{appletName}; # replace the current appletName if non-empty
  513     $self->{appletName};
  514 }
  515 sub debugMode {
  516   my $self = shift;
  517   my $new_flag = shift;
  518   $self->{debugMode} = $new_flag if defined($new_flag);
  519   $self->{debugMode};
  520 }
  521 sub appletId {
  522   appletName(@_);
  523 }
  524 sub maxInitializationAttempts {
  525   my $self = shift;
  526   $self->{maxInitializationAttempts} = shift || $self->{maxInitializationAttempts};
  527   $self->{maxInitializationAttempts};
  528 }
  529 sub initialState {
  530   my $self = shift;
  531   my $str = shift;
  532   $self->{initialState} = $str   ||$self->{initialState}; # replace the current string if non-empty
  533     $self->{initialState};
  534 }
  535 
  536 sub config {
  537   my $self = shift;
  538   my $str = shift;
  539   $self->{base64_config} =  encode_base64($str)   || $self->{base64_config}; # replace the current string if non-empty
  540   $self->{base64_config} =~ s/\n//g;
  541     decode_base64($self->{base64_config});
  542 }
  543 #######################
  544 # soon to be deprecated?
  545 #######################
  546 sub state {
  547   my $self = shift;
  548   my $str = shift;
  549   $self->{base64_state} =  encode_base64($str)   ||$self->{base64_state}; # replace the current string if non-empty
  550   $self->{base64_state} =~ s/\n//g;
  551     decode_base64($self->{base64_state});
  552 }
  553 sub base64_state{
  554   my $self = shift;
  555   $self->{base64_state} = shift ||$self->{base64_state}; # replace the current string if non-empty
  556     $self->{base64_state};
  557 }
  558 
  559 sub base64_config {
  560   my $self = shift;
  561   $self->{base64_config} = shift ||$self->{base64_config}; # replace the current string if non-empty
  562   $self->{base64_config} =$self->{base64_config};
  563     $self->{base64_config};
  564 }
  565 
  566 sub returnFieldName {
  567   my $self = shift;
  568     warn "use  answerBoxName  instead of returnFieldName";
  569 }
  570 sub answerBox {
  571   my $self = shift;
  572     warn "use  answerBoxAlias  instead of AnswerBox";
  573 }
  574 #########################
  575 #FIXME
  576 # need to be able to adjust header material
  577 
  578 sub insertHeader {
  579     my $self = shift;
  580 
  581     my $codebase              =  $self->codebase;
  582     my $appletId              =  $self->appletId;
  583     my $appletName            =  $self->appletName;
  584     my $base64_initialState   =  $self->base64_state;
  585     my $initializeActionAlias =  $self->initializeActionAlias;
  586     my $submitActionAlias     =  $self->submitActionAlias;
  587     my $submitActionScript    =  $self->submitActionScript;
  588     my $setStateAlias         =  $self->setStateAlias;
  589     my $getStateAlias         =  $self->getStateAlias;
  590 
  591     my $setConfigAlias        =  $self->setConfigAlias;
  592     my $getConfigAlias        =  $self->getConfigAlias;
  593     my $maxInitializationAttempts = $self->maxInitializationAttempts;
  594     my $base64_config         =  $self->base64_config;
  595     my $debugMode             =  ($self->debugMode) ? "1": "0";
  596     my $answerBoxAlias        =  $self->{answerBoxAlias};
  597     my $headerText            =  $self->header();
  598 
  599 
  600     $submitActionScript =~ s/"/\\"/g;    # escape quotes for ActionScript
  601                                          # other variables should not have quotes.
  602 
  603     $submitActionScript =~ s/\n/ /g;     # replace returns with spaces -- returns in the wrong spot can cause trouble with javaScript
  604     $submitActionScript =~ s/\r/ /g;     # replace returns with spaces -- returns can cause trouble
  605     my  $base64_submitActionScript =     encode_base64($submitActionScript);
  606     $base64_submitActionScript =~s/\n//g;
  607 
  608     $headerText =~ s/(\$\w+)/$1/gee;   # interpolate variables p17 of Cookbook
  609 
  610     return $headerText;
  611 
  612 
  613 }
  614 
  615 sub insertObject {
  616     my $self       = shift;
  617     my $code       = $self->{code};
  618     my $codebase   = $self->{codebase};
  619     my $appletId   = $self->{appletName};
  620     my $appletName = $self->{appletName};
  621     my $archive    = $self->{archive};
  622     my $width      = $self->{width};
  623     my $height     = $self->{height};
  624     my $applet_bgcolor = $self->{bgcolor};
  625     my $javaParameters = '';
  626     my $flashParameters = '';
  627     my %param_hash = %{$self->params()};
  628     foreach my $key (keys %param_hash) {
  629       $javaParameters .= qq!<param name ="$key"  value = "$param_hash{$key}">\n!;
  630       $flashParameters .= uri_escape($key).'='.uri_escape($param_hash{$key}).'&';
  631     }
  632     $flashParameters =~ s/\&$//;    # trim last &
  633 
  634 
  635     $objectText = $self->{objectText};
  636     $objectText =~ s/(\$\w+)/$1/gee;
  637     return $objectText;
  638 }
  639 # sub initialize  {
  640 #     my $self = shift;
  641 #   return q{
  642 #     <script>
  643 #       initializeAllApplets();
  644 #       // this should really be done in the <body> tag
  645 #     </script>
  646 #   };
  647 #
  648 # }
  649 ########################################################
  650 # HEADER material for one flash or java applet
  651 ########################################################
  652 
  653 use constant DEFAULT_HEADER_TEXT =><<'END_HEADER_SCRIPT';
  654     <script src="/webwork2_files/js/Base64.js" language="javascript">
  655     </script>
  656     <script src="/webwork2_files/js/ww_applet_support.js" language="javascript">
  657         //upload functions stored in /opt/webwork/webwork2/htdocs/js ...
  658 
  659      </script>
  660   <script language="JavaScript">
  661 
  662 
  663 
  664     //////////////////////////////////////////////////////////
  665   //TEST code
  666   //
  667     //
  668     //////////////////////////////////////////////////////////
  669 
  670     ww_applet_list["$appletName"] = new ww_applet("$appletName");
  671 
  672 
  673   ww_applet_list["$appletName"].code = "$code";
  674   ww_applet_list["$appletName"].codebase         = "$codebase";
  675     ww_applet_list["$appletName"].appletID         = "$appletID";
  676   ww_applet_list["$appletName"].base64_state     = "$base64_initializationState";
  677   ww_applet_list["$appletName"].initialState     = Base64.decode("$base64_intialState");
  678   ww_applet_list["$appletName"].base64_config    = "$base64_config";
  679   ww_applet_list["$appletName"].getStateAlias    = "$getStateAlias";
  680   ww_applet_list["$appletName"].setStateAlias    = "$setStateAlias";
  681   ww_applet_list["$appletName"].setConfigAlias   = "$setConfigAlias";
  682   ww_applet_list["$appletName"].getConfigAlias   = "$getConfigAlias";
  683   ww_applet_list["$appletName"].initializeActionAlias = "$initializeActionAlias";
  684   ww_applet_list["$appletName"].submitActionAlias = "$submitActionAlias";
  685   ww_applet_list["$appletName"].submitActionScript = Base64.decode("$submitActionScript_base64");
  686   ww_applet_list["$appletName"].answerBoxAlias = "$answerBoxAlias";
  687   ww_applet_list["$appletName"].maxInitializationAttempts = $maxInitializationAttempts;
  688   ww_applet_list["$appletName"].debugMode = "$debugMode";
  689 
  690     </script>
  691 
  692 END_HEADER_SCRIPT
  693 
  694 package FlashApplet;
  695 @ISA = qw(Applet);
  696 
  697 
  698 =head2 Insertion HTML code for FlashApplet
  699 
  700 =pod
  701 
  702 The secret to making this applet work with IE in addition to normal browsers
  703 is the addition of the C(<form></form>) construct just before the object.
  704 
  705 For some reason IE has trouble locating a flash object which is contained
  706 within a form.  Adding this second blank form with the larger problemMainForm
  707 seems to solve the problem.
  708 
  709 This follows method2 of the advice given in url(http://kb.adobe.com/selfservice/viewContent.do?externalId=kb400730&sliceId=2)
  710 Method1 and methods involving SWFObject(Geoff Stearns) and SWFFormFix (Steve Kamerman) have yet to be fully investigated:
  711 http://devel.teratechnologies.net/swfformfix/swfobject_swfformfix_source.js
  712 http://www.teratechnologies.net/stevekamerman/index.php?m=01&y=07&entry=entry070101-033933
  713 
  714     use constant DEFAULT_OBJECT_TEXT =><<'END_OBJECT_TEXT';
  715       <form></form>
  716       <object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
  717            id="$appletName" width="500" height="375"
  718            codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab">
  719          <param name="movie" value="$codebase/$appletName.swf" />
  720          <param name="quality" value="high" />
  721          <param name="bgcolor" value="$applet_bgcolor" />
  722          <param name="allowScriptAccess" value="sameDomain" />
  723          <embed src="$codebase/$appletName.swf" quality="high" bgcolor="$applet_bgcolor"
  724            width="$width" height="$height" name="$appletName" align="middle" id="$appletName"
  725            play="true" loop="false" quality="high" allowScriptAccess="sameDomain"
  726            type="application/x-shockwave-flash"
  727            pluginspage="http://www.macromedia.com/go/getflashplayer">
  728          </embed>
  729 
  730        </object>
  731     END_OBJECT_TEXT
  732 
  733 
  734 =cut
  735 
  736 use constant DEFAULT_OBJECT_TEXT =><<'END_OBJECT_TEXT';
  737   <form></form>
  738   <object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
  739              id="$appletName" width="500" height="375"
  740              codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab">
  741          <param name="movie" value="$codebase/$appletName.swf" />
  742          <param name="quality" value="high" />
  743          <param name="bgcolor" value="$applet_bgcolor" />
  744          <param name="allowScriptAccess" value="sameDomain" />
  745          <param name="FlashVars" value="$flashParameters"/>
  746          <embed src="$codebase/$appletName.swf" quality="high" bgcolor="$applet_bgcolor"
  747              width="$width" height="$height" name="$appletName" align="middle" id="$appletName"
  748              play="true" loop="false" quality="high" allowScriptAccess="sameDomain"
  749              type="application/x-shockwave-flash"
  750              pluginspage="http://www.macromedia.com/go/getflashplayer"
  751              FlashVars="$flashParameters">
  752          </embed>
  753 
  754      </object>
  755 END_OBJECT_TEXT
  756 
  757 sub new {
  758     my $class = shift;
  759   $class -> SUPER::new( objectText   => DEFAULT_OBJECT_TEXT(),
  760                   @_
  761   );
  762 
  763 }
  764 
  765 
  766 package JavaApplet;
  767 @ISA = qw(Applet);
  768 
  769 =head2 Insertion HTML code for JavaApplet
  770 
  771 =pod
  772 
  773 The secret to making this applet work with IE in addition to normal browsers
  774 is the addition of the C(<form></form>) construct just before the object.
  775 
  776 For some reason IE has trouble locating a flash object which is contained
  777 within a form.  Adding this second blank form with the larger problemMainForm
  778 seems to solve the problem.
  779 
  780 This follows method2 of the advice given in url(http://kb.adobe.com/selfservice/viewContent.do?externalId=kb400730&sliceId=2)
  781 Method1 and methods involving SWFObject(Geoff Stearns) and SWFFormFix (Steve Kamerman) have yet to be fully investigated:
  782 http://devel.teratechnologies.net/swfformfix/swfobject_swfformfix_source.js
  783 http://www.teratechnologies.net/stevekamerman/index.php?m=01&y=07&entry=entry070101-033933
  784 
  785     use constant DEFAULT_OBJECT_TEXT =><<'END_OBJECT_TEXT';
  786       <form></form>
  787      <applet
  788       code     = "$code"
  789       codebase = "$codebase"
  790       archive  = "$archive"
  791       name     = "$appletName"
  792       id       = "$appletName"
  793       width    = "$width"
  794       height   = "$height"
  795       MAYSCRIPT
  796      >
  797       $javaParameters
  798      </applet>
  799     END_OBJECT_TEXT
  800 
  801 =cut
  802 
  803 use constant DEFAULT_OBJECT_TEXT =><<'END_OBJECT_TEXT';
  804   <form></form>
  805  <applet
  806   code     = "$code"
  807   codebase = "$codebase"
  808   archive  = "$archive"
  809   name     = "$appletName"
  810     id       = "$appletName"
  811     width    = "$width"
  812     height   = "$height"
  813     bgcolor  = "$applet_bgcolor"
  814     MAYSCRIPT
  815  >
  816   $javaParameters
  817 
  818   Sorry, the Applet could not be started. Please make sure that
  819 Java 1.4.2 (or later) is installed and activated.
  820 (<a href="http://java.sun.com/getjava">click here to install Java now</a>)
  821  </applet>
  822 END_OBJECT_TEXT
  823 
  824 sub new {
  825     my $class = shift;
  826   $class -> SUPER::new( objectText   => DEFAULT_OBJECT_TEXT(),
  827                   @_
  828   );
  829 
  830 }
  831 
  832 
  833 
  834 1;

aubreyja at gmail dot com
ViewVC Help
Powered by ViewVC 1.0.9