[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 5676 - (download) (as text) (annotate)
Thu May 22 19:15:59 2008 UTC (11 years, 5 months ago) by gage
File size: 23395 byte(s)
minor changes to help with debugging.

    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.11 2008/05/12 00:50:23 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   my $appletName = "LineThruPointsWW";
   27   $applet = new FlashApplet(
   28      # can be replaced by $applet =FlashApplet() when using AppletObjects.pl
   29      codebase   => findAppletCodebase("$appletName.swf"),
   30      appletName => $appletName,
   31      appletId   => $appletName,
   32      submitActionAlias => 'checkAnswer',
   33   );
   34 
   35   ###################################
   36   # Configure applet
   37   ###################################
   38 
   39   #xml data to set up the problem-rac
   40   $applet->config(qq{<XML>
   41   <point xval='$xval_1' yval='$yval_1' />
   42   <point xval='$xval_2' yval='$yval_2' />
   43   </XML>});
   44 
   45 
   46   ###################################
   47   # insert applet header material
   48   ###################################
   49   HEADER_TEXT($applet->insertHeader );
   50 
   51   ###################################
   52   # Text section
   53   #
   54 
   55   ###################################
   56   #insert applet into body
   57   ###################################
   58   TEXT( MODES(TeX=>'object code', HTML=>$applet->insertObject));
   59 
   60 
   61 =head1 DESCRIPTION
   62 
   63 This file provides an object to store in one place
   64 all of the information needed to call an applet.
   65 
   66 The object FlashApplet has defaults for inserting flash applets.
   67 
   68 =over
   69 
   70 =item *
   71 
   72 =item *
   73 
   74 =back
   75 
   76 (not yet completed)
   77 
   78 The module JavaApplet has defaults for inserting java applets.
   79 
   80 The module Applet stores common code for the two types of applet.
   81 
   82 =head1 USAGE
   83 
   84 These modules are activate by listing it in the modules section of global.conf and rebooting the server.
   85 The companion file to this one is macros/AppletObjects.pl
   86 
   87 qw(Applet FlashApplet JavaApplet)
   88 
   89 =cut
   90 
   91 
   92 
   93 package Applet;
   94 
   95 use URI::Escape;
   96 
   97 
   98 
   99 use MIME::Base64 qw( encode_base64 decode_base64);
  100 
  101 
  102 =head2 Default javaScript functions placed in header
  103 
  104 These functions are automatically defined for use for
  105 any javaScript placed in the text of a PG question.
  106 
  107   getApplet(appletName)  -- finds the applet path in the DOM
  108 
  109   submitAction()            -- calls the submit action of the applets
  110 
  111 
  112     initializeAction()        -- calls the initialize action of the applets
  113 
  114     getQE(name)               -- gets an HTML element of the question by name
  115                                  or by id.  Be sure to keep all names and ids
  116                                  unique within a given PG question.
  117 
  118     getQuestionElement(name)  -- long form of getQE(name)
  119 
  120     listQuestionElements()    -- for discovering the names of inputs in the
  121                                  PG question.  An alert dialog will list all
  122                                  of the elements.
  123              Usage: Place this at the END of the question,
  124              just before END_DOCUMENT():
  125 
  126               TEXT(qq!<script> listQuestionElements() </script>!);
  127         ENDDOCUMENT();
  128 
  129     list of  accessor methods  format:  current_value = $self->method(new_value or empty)
  130 
  131     appletId         for simplicity and reliability appletId and appletName are always the same
  132     appletName
  133 
  134     archive      the name of the .jar file containing the applet code
  135     code         the name of the applet code in the .jar archive
  136     codebase     a prefix url used to find the archive and the applet itself
  137 
  138     height       rectangle alloted in the html page for displaying the applet
  139     width
  140 
  141     params       an anonymous array containing name/value pairs
  142                  to configure the applet [name =>'value, ...]
  143 
  144     header       stores the text to be added to the header section of the html page
  145         object       stores the text which places the applet on the html page
  146 
  147     debug        in debug mode several alerts mark progress through the procedure of calling the applet
  148 
  149     config       configuration are those customizable attributes of the applet which don't
  150                  change as it is used.  When stored in hidden answer fields
  151                  it is usually stored in base64 encoded format.
  152     base64_config base64 encode version of the contents of config
  153 
  154     configAlias  (default: config ) names the applet command called with the contents of $self->config
  155                  to configure the applet.  The parameters are passed to the applet in plain text using <xml>
  156                  The outer tags must be   <xml> .....   </xml>
  157     state        state consists of those customizable attributes of the applet which change
  158                  as the applet is used.  It is stored by the calling .pg question so that
  159                  when revisiting the question the applet
  160                  will be restored to the same state it was left in when the question was last
  161                  viewed.
  162 
  163     getStateAlias  (default: getState) alias for command called to read the current state of the applet.
  164                    The state is passed in plain text xml format with outer tags: <xml>....</xml>
  165     setStateAlias  (default: setState) alias for the command called to reset the  state of the applet.
  166                    The state is passed in plain text in xml format with outer tags: <xml>....</xml>
  167 
  168     base64_state   returns the base64 encoded version of the state stored in the applet object.
  169 
  170     initializeActionAlias  -- (default: initializeAction) the name of the javaScript subroutine called to initialize the applet (some overlap with config/ and setState
  171         submitActionAlias      -- (default: submitAction)the name of the javaScript subroutine called when the submit button of the
  172                                   .pg question is pressed.
  173 
  174     returnFieldName
  175 
  176 
  177 
  178 
  179 
  180 =cut
  181 
  182 
  183 
  184 
  185 sub new {
  186    my $class = shift;
  187    my $self = {
  188     appletName =>'',
  189     code=>'',
  190     codebase=>'',
  191 #   appletId  =>'',   #always use identical applet Id's and applet Names
  192     params    =>undef,
  193     width     => 550,
  194     height    => 400,
  195     base64_state       =>  undef,     # this is an state to use for initializing the first occurence of the question.
  196     base64_config      =>  undef,     # this is the initial (and final?) configuration
  197     getStateAlias      =>  'getXML',
  198     setStateAlias      =>  'setXML',
  199     configAlias        =>  'config',
  200     initializeActionAlias => 'setXML',
  201     submitActionAlias  =>  'getXML',
  202     returnFieldName    =>  'receivedField',
  203     headerText         =>  DEFAULT_HEADER_TEXT(),
  204     objectText         => '',
  205     debug              => 0,
  206     @_,
  207   };
  208   bless $self, $class;
  209   $self->state('<xml></xml>');
  210   $self->config('<xml></xml>');
  211   return $self;
  212 }
  213 
  214 sub  header {
  215   my $self = shift;
  216   if ($_[0] eq "reset") {  # $applet->header('reset');  erases default header text.
  217     $self->{headerText}='';
  218   } else {
  219     $self->{headerText} .= join("",@_);  # $applet->header(new_text); concatenates new_text to existing header.
  220   }
  221     $self->{headerText};
  222 }
  223 sub  object {
  224   my $self = shift;
  225   if ($_[0] eq "reset") {
  226     $self->{objectText}='';
  227   } else {
  228     $self->{objectText} .= join("",@_);
  229   }
  230     $self->{objectText};
  231 }
  232 sub params {
  233   my $self = shift;
  234   if (ref($_[0]) =~/HASH/) {
  235     $self->{params} = shift;
  236   } elsif ( !defined($_[0]) or $_[0] =~ '') {
  237     # do nothing (read)
  238   } else {
  239     warn "You must enter a reference to a hash for the parameter list";
  240   }
  241   $self->{params};
  242 }
  243 
  244 sub initializeActionAlias {
  245   my $self = shift;
  246   $self->{initializeActionAlias} = shift ||$self->{initializeActionAlias}; # replace the current contents if non-empty
  247     $self->{initializeActionAlias};
  248 }
  249 
  250 sub submitActionAlias {
  251   my $self = shift;
  252   $self->{submitActionAlias} = shift ||$self->{submitActionAlias}; # replace the current contents if non-empty
  253     $self->{submitActionAlias};
  254 }
  255 sub getStateAlias {
  256   my $self = shift;
  257   $self->{getStateAlias} = shift ||$self->{getStateAlias}; # replace the current contents if non-empty
  258     $self->{getStateAlias};
  259 }
  260 
  261 sub setStateAlias {
  262   my $self = shift;
  263   $self->{setStateAlias} = shift ||$self->{setStateAlias}; # replace the current contents if non-empty
  264     $self->{setStateAlias};
  265 }
  266 sub configAlias {
  267   my $self = shift;
  268   $self->{configAlias} = shift ||$self->{configAlias}; # replace the current contents if non-empty
  269     $self->{configAlias};
  270 }
  271 sub returnFieldName {
  272   my $self = shift;
  273   $self->{returnFieldName} = shift ||$self->{returnFieldName}; # replace the current contents if non-empty
  274     $self->{returnFieldName};
  275 }
  276 sub codebase {
  277   my $self = shift;
  278   $self->{codebase} = shift ||$self->{codebase}; # replace the current codebase if non-empty
  279     $self->{codebase};
  280 }
  281 sub code {
  282   my $self = shift;
  283   $self->{code} = shift ||$self->{code}; # replace the current code if non-empty
  284     $self->{code};
  285 }
  286 sub height {
  287   my $self = shift;
  288   $self->{height} = shift ||$self->{height}; # replace the current height if non-empty
  289     $self->{height};
  290 }
  291 sub width {
  292   my $self = shift;
  293   $self->{width} = shift ||$self->{width}; # replace the current width if non-empty
  294     $self->{width};
  295 }
  296 sub archive {
  297   my $self = shift;
  298   $self->{archive} = shift ||$self->{archive}; # replace the current archive if non-empty
  299     $self->{archive};
  300 }
  301 sub appletName {
  302   my $self = shift;
  303   $self->{appletName} = shift ||$self->{appletName}; # replace the current appletName if non-empty
  304     $self->{appletName};
  305 }
  306 sub debug {
  307   my $self = shift;
  308   my $new_flag = shift;
  309   $self->{debug} = $new_flag if defined($new_flag);
  310   $self->{debug};
  311 }
  312 sub appletId {
  313   appletName(@_);
  314 }
  315 sub state {
  316   my $self = shift;
  317   my $str = shift;
  318   $self->{base64_state} =  encode_base64($str)   ||$self->{base64_state}; # replace the current string if non-empty
  319   $self->{base64_state} =~ s/\n//g;
  320     decode_base64($self->{base64_state});
  321 }
  322 
  323 sub base64_state{
  324   my $self = shift;
  325   $self->{base64_state} = shift ||$self->{base64_state}; # replace the current string if non-empty
  326     $self->{base64_state};
  327 }
  328 sub config {
  329   my $self = shift;
  330   my $str = shift;
  331   $self->{base64_config} =  encode_base64($str)   || $self->{base64_config}; # replace the current string if non-empty
  332   $self->{base64_config} =~ s/\n//g;
  333     decode_base64($self->{base64_config});
  334 }
  335 sub base64_config {
  336   my $self = shift;
  337   $self->{base64_config} = shift ||$self->{base64_config}; # replace the current string if non-empty
  338   $self->{base64_config} =$self->{base64_config};
  339     $self->{base64_config};
  340 }
  341 #FIXME
  342 # need to be able to adjust header material
  343 
  344 sub insertHeader {
  345     my $self = shift;
  346     my $codebase         =  $self->codebase;
  347     my $appletId         =  $self->appletId;
  348     my $appletName       =  $self->appletName;
  349     my $base64_initialState     = $self->base64_state;
  350     my $initializeAction =  $self->initializeActionAlias;
  351     my $submitAction     =  $self->submitActionAlias;
  352     my $setState         =  $self->setStateAlias;
  353     my $getState         =  $self->getStateAlias;
  354     my $config           =  $self->configAlias;
  355     my $base64_config    =  $self->base64_config;
  356     my $debugMode        =  ($self->debug) ? "1": "0";
  357     my $returnFieldName  =  $self->{returnFieldName};
  358 #    my $encodeStateQ    =  ($self->debug)?'' : "state = Base64.encode(state);";              # in debug mode base64 encoding is not used.
  359 #     my $decodeStateQ   =  "if (!state.match(/<XML>*/i) ) {state = Base64.decode(state)}";   # decode if <XML> is not present
  360     my $headerText       =  $self->header();
  361 
  362     $headerText =~ s/(\$\w+)/$1/gee;   # interpolate variables p17 of Cookbook
  363 
  364     return $headerText;
  365 
  366 
  367 }
  368 
  369 sub insertObject {
  370     my $self       = shift;
  371     my $code       = $self->{code};
  372     my $codebase   = $self->{codebase};
  373     my $appletId   = $self->{appletName};
  374     my $appletName = $self->{appletName};
  375     my $archive    = $self->{archive};
  376     my $width      = $self->{width};
  377     my $height     = $self->{height};
  378     my $javaParameters = '';
  379     my $flashParameters = '';
  380     my %param_hash = %{$self->params()};
  381     foreach my $key (keys %param_hash) {
  382       $javaParameters .= qq!<param name ="$key"  value = "$param_hash{$key}">\n!;
  383       $flashParameters .= uri_escape($key).'='.uri_escape($param_hash{$key}).'&';
  384     }
  385     $flashParameters =~ s/\&$//;    # trim last &
  386 
  387 
  388     $objectText = $self->{objectText};
  389     $objectText =~ s/(\$\w+)/$1/gee;
  390     return $objectText;
  391 }
  392 sub initialize  {
  393     my $self = shift;
  394   return q{
  395     <script>
  396       initializeAction();
  397       // this should really be done in the <body> tag
  398     </script>
  399   };
  400 
  401 }
  402 ########################################################
  403 # HEADER material for one flash or java applet
  404 ########################################################
  405 
  406 use constant DEFAULT_HEADER_TEXT =><<'END_HEADER_SCRIPT';
  407 
  408   <script language="JavaScript">
  409 
  410   // set debug mode for this applet
  411     set_debug($debugMode);
  412 
  413   //////////////////////////////////////////////////////////
  414   //CONFIGURATIONS
  415   //
  416     // configurations are "permanent"
  417     //////////////////////////////////////////////////////////
  418 
  419     applet_config_list["$appletName"]   = function() {
  420         debug_add("applet_config_list:\n attempt to configure $appletName . $config ( $base64_config ) if config function is defined: "
  421         );
  422       try {
  423           if (( typeof(getApplet("$appletName").$config)  == "function" ) ) {
  424               debug_add("CONFIGURE $appletName");
  425           getApplet("$appletName").$config(Base64.decode("$base64_config"));
  426         }
  427       } catch(e) {
  428         alert("Error executing configuration command $config for $appletName: " + e );
  429       }
  430     }
  431     ////////////////////////////////////////////////////////////
  432     //
  433     //STATE:
  434     // state can vary as the applet is manipulated -- it is reset from the questions _state values
  435     //
  436     //////////////////////////////////////////////////////////
  437 
  438     applet_setState_list["$appletName"] = function(state) {
  439     debug_add("Begin setState for applet $appletName");
  440     debug_add("Obtain state from $appletName"+"_state");
  441     state =  state || getQE("$appletName"+"_state").value;
  442     if ( base64Q(state) ) {
  443       state=Base64.decode(state);
  444     }
  445     if (state.match(/<xml/i) || state.match(/<?xml/i) ) {  // if state starts with <?xml
  446 
  447       debug_add("applet_setState_list: \n set (decoded) state for $appletName to " +
  448            state +"\nfunction type is " +typeof(getApplet("$appletName").$setState)
  449       );
  450       try {
  451       if (( typeof(getApplet("$appletName").$setState)  =="function" ) ) {
  452         debug_add("setState for $appletName");
  453         getApplet("$appletName").$setState( state );
  454       }
  455       } catch(e) {
  456       alert("Error in setting state of $appletName using command $setState : " + e );
  457       }
  458     } else if (debug) {
  459       alert("new state was empty string or did not begin with <xml-- state was not reset");
  460     }
  461   };
  462   applet_getState_list["$appletName"] = function () {
  463     debug_add("get current state for applet $appletName and store it in $appletName"+"_state");
  464     var applet = getApplet("$appletName");
  465     try {
  466       if (( typeof(applet.$getState)  == "function" ) ) {  // there may be no state function
  467         state  = applet.$getState();                     // get state in xml format
  468         debug_add("state has type " + typeof(state));
  469         state  = String(state);                          // geogebra returned an object type instead of a string type
  470         debug_add("state converted to type " + typeof(state));
  471       }
  472 
  473       if (!debug) {
  474         state = Base64.encode(state);
  475       };   // replace state by encoded version unless in debug mode
  476 
  477       debug_add("state is "+state);                  // this should still be in plain text
  478       getQE("$appletName"+"_state").value = state;   //place state in input item (debug: textarea, otherwise: hidden)
  479     } catch (e) {
  480       alert("Error in getting state for $appletName " + e );
  481     }
  482     };
  483 
  484     ////////////////////////////////////////////////////////////
  485     //
  486     //INITIALIZE
  487     //
  488     ////////////////////////////////////////////////////////////
  489 
  490 
  491     applet_checkLoaded_list["$appletName"] = function() { // this function returns 0 unless:
  492                                                       // applet has already been flagged as ready in applet_isReady_list
  493                                                       // applet.config is defined  (or alias for .config)
  494                                                       // applet.setState is defined
  495                                                       // applet.isActive is defined
  496                                                       // applet reported that it is loaded by calling loadQ()
  497       var ready = 0;
  498       var applet = getApplet("$appletName");
  499           if (!debug && applet_isReady_list["$appletName"]) {return(1)}; // memorize readiness in non-debug mode
  500         if ( typeof(applet.$config) == "function") {
  501             debug_add( "applet.config is " + typeof(applet.$config) );
  502           ready = 1;
  503         }
  504         if( typeof(applet.$getState) == "function") {
  505             debug_add( "applet.getState is " + typeof(applet.$getState) );
  506           ready =1;
  507         }
  508         if (typeof(applet.isActive) == "function" && applet.isActive ) {
  509           debug_add( "applet.isActive is " + typeof(applet.isActive) );
  510           ready =1;
  511         }
  512         if (typeof(applet_reportsLoaded_list["$appletName"]) !="undefined" && applet_reportsLoaded_list["$appletName"] != 0 ) {
  513           debug_add( "applet reports that it is loaded " + applet_reportsLoaded_list["$appletName"] );
  514           ready =1;
  515         }
  516       applet_isReady_list["$appletName"]= ready;
  517       return(ready);
  518     }
  519 
  520     applet_initializeAction_list["$appletName"] = function (state) {
  521           applet_setState_list["$appletName"](state);
  522   };
  523 
  524   applet_submitAction_list["$appletName"] = function () {
  525         if (! applet_isReady_list["$appletName"]  ) {
  526           alert("$appletName is not ready");
  527         }
  528           applet_getState_list["$appletName"]();
  529       //getQE("$returnFieldName").value = getApplet("$appletName").sendData();  //FIXME -- not needed in general?
  530     };
  531     </script>
  532 
  533 END_HEADER_SCRIPT
  534 
  535 package FlashApplet;
  536 @ISA = qw(Applet);
  537 
  538 
  539 
  540 =pod
  541 
  542 The secret to making this applet work with IE in addition to normal browsers
  543 is the addition of the C(<form></form>) construct just before the object.
  544 
  545 For some reason IE has trouble locating a flash object which is contained
  546 within a form.  Adding this second blank form with the larger problemMainForm
  547 seems to solve the problem.
  548 
  549 This follows method2 of the advice given in url(http://kb.adobe.com/selfservice/viewContent.do?externalId=kb400730&sliceId=2)
  550 Method1 and methods involving SWFObject(Geoff Stearns) and SWFFormFix (Steve Kamerman) have yet to be fully investigated:
  551 http://devel.teratechnologies.net/swfformfix/swfobject_swfformfix_source.js
  552 http://www.teratechnologies.net/stevekamerman/index.php?m=01&y=07&entry=entry070101-033933
  553 
  554     use constant DEFAULT_OBJECT_TEXT =><<'END_OBJECT_TEXT';
  555       <form></form>
  556       <object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
  557            id="$appletName" width="500" height="375"
  558            codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab">
  559          <param name="movie" value="$codebase/$appletName.swf" />
  560          <param name="quality" value="high" />
  561          <param name="bgcolor" value="#869ca7" />
  562          <param name="allowScriptAccess" value="sameDomain" />
  563          <embed src="$codebase/$appletName.swf" quality="high" bgcolor="#869ca7"
  564            width="$width" height="$height" name="$appletName" align="middle" id="$appletName"
  565            play="true" loop="false" quality="high" allowScriptAccess="sameDomain"
  566            type="application/x-shockwave-flash"
  567            pluginspage="http://www.macromedia.com/go/getflashplayer">
  568          </embed>
  569 
  570        </object>
  571     END_OBJECT_TEXT
  572 
  573 
  574 =cut
  575 
  576 use constant DEFAULT_OBJECT_TEXT =><<'END_OBJECT_TEXT';
  577   <form></form>
  578   <object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
  579              id="$appletName" width="500" height="375"
  580              codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab">
  581          <param name="movie" value="$codebase/$appletName.swf" />
  582          <param name="quality" value="high" />
  583          <param name="bgcolor" value="#869ca7" />
  584          <param name="allowScriptAccess" value="sameDomain" />
  585          <param name="FlashVars" value="$flashParameters"/>
  586          <embed src="$codebase/$appletName.swf" quality="high" bgcolor="#869ca7"
  587              width="$width" height="$height" name="$appletName" align="middle" id="$appletName"
  588              play="true" loop="false" quality="high" allowScriptAccess="sameDomain"
  589              type="application/x-shockwave-flash"
  590              pluginspage="http://www.macromedia.com/go/getflashplayer"
  591              FlashVars="$flashParameters">
  592          </embed>
  593 
  594      </object>
  595 END_OBJECT_TEXT
  596 
  597 sub new {
  598     my $class = shift;
  599   $class -> SUPER::new( objectText   => DEFAULT_OBJECT_TEXT(),
  600                   @_
  601   );
  602 
  603 }
  604 
  605 
  606 package JavaApplet;
  607 @ISA = qw(Applet);
  608 
  609 
  610 
  611 =pod
  612 
  613 The secret to making this applet work with IE in addition to normal browsers
  614 is the addition of the C(<form></form>) construct just before the object.
  615 
  616 For some reason IE has trouble locating a flash object which is contained
  617 within a form.  Adding this second blank form with the larger problemMainForm
  618 seems to solve the problem.
  619 
  620 This follows method2 of the advice given in url(http://kb.adobe.com/selfservice/viewContent.do?externalId=kb400730&sliceId=2)
  621 Method1 and methods involving SWFObject(Geoff Stearns) and SWFFormFix (Steve Kamerman) have yet to be fully investigated:
  622 http://devel.teratechnologies.net/swfformfix/swfobject_swfformfix_source.js
  623 http://www.teratechnologies.net/stevekamerman/index.php?m=01&y=07&entry=entry070101-033933
  624 
  625     use constant DEFAULT_OBJECT_TEXT =><<'END_OBJECT_TEXT';
  626       <form></form>
  627      <applet
  628       code     = "$code"
  629       codebase = "$codebase"
  630       archive  = "$archive"
  631       name     = "$appletName"
  632       id       = "$appletName"
  633       width    = "$width"
  634       height   = "$height"
  635       MAYSCRIPT
  636      >
  637       $javaParameters
  638      </applet>
  639     END_OBJECT_TEXT
  640 
  641 =cut
  642 
  643 use constant DEFAULT_OBJECT_TEXT =><<'END_OBJECT_TEXT';
  644   <form></form>
  645  <applet
  646   code     = "$code"
  647   codebase = "$codebase"
  648   archive  = "$archive"
  649   name     = "$appletName"
  650     id       = "$appletName"
  651     width    = "$width"
  652     height   = "$height"
  653     MAYSCRIPT
  654  >
  655   $javaParameters
  656 
  657   Sorry, the Applet could not be started. Please make sure that
  658 Java 1.4.2 (or later) is installed and activated.
  659 (<a href="http://java.sun.com/getjava">click here to install Java now</a>)
  660  </applet>
  661 END_OBJECT_TEXT
  662 
  663 sub new {
  664     my $class = shift;
  665   $class -> SUPER::new( objectText   => DEFAULT_OBJECT_TEXT(),
  666                   @_
  667   );
  668 
  669 }
  670 
  671 
  672 
  673 1;

aubreyja at gmail dot com
ViewVC Help
Powered by ViewVC 1.0.9