[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 5594 - (download) (as text) (annotate)
Thu Dec 20 00:04:39 2007 UTC (11 years, 11 months ago) by gage
File size: 14136 byte(s)
Updated documentation.  Fixed a hard coded reference in the DEFAULT_OBJECT_TEXT.

Added getQE(name) for referencing HTML elements in PG questions.

Added listQuestionElements()  for discovering the names/ids of input HTML elements in PG questions.

    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.3 2007/11/06 16:47:19 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->xmlString(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 will store common code for the two types of applet.
   81 
   82 =head1 USAGE
   83 
   84 This file is included by listing it in the modules section of global.conf.
   85 
   86 =cut
   87 
   88 
   89 
   90 package Applet;
   91 
   92 
   93 package FlashApplet;
   94 
   95 
   96 use MIME::Base64 qw( encode_base64 decode_base64);
   97 
   98 
   99 =head2 Default javaScript functions placed in header
  100 
  101 These functions are automatically defined for use for
  102 any javaScript placed in the text of a PG question.
  103 
  104   getFlashMovie(appletName)  -- finds the applet path in the DOM
  105 
  106   submitAction()            -- calls the submit action of the applet
  107                             -- the submitAction is defined
  108 
  109     initialize()              -- calls the initialize action of the applet
  110 
  111     getQE(name)               -- gets an HTML element of the question by name
  112                                  or by id.  Be sure to keep all names and ids
  113                                  unique within a given PG question.
  114 
  115     getQuestionElement(name)  -- long form of getQE(name)
  116 
  117     listQuestionElements()    -- for discovering the names of inputs in the
  118                                  PG question.  An alert dialog will list all
  119                                  of the elements.
  120              Usage: Place this at the END of the question,
  121              just before END_DOCUMENT():
  122 
  123               TEXT(qq!<script> listQuestionElements() </script>!);
  124         ENDDOCUMENT();
  125 
  126 
  127 =cut
  128 
  129 
  130 use constant DEFAULT_HEADER_TEXT =><<'END_HEADER_SCRIPT';
  131     <script language="javascript">AC_FL_RunContent = 0;</script>
  132     <script src="http://hosted2.webwork.rochester.edu/webwork2_files/applets/AC_RunActiveContent.js" language="javascript">
  133     </script>
  134 
  135 
  136   <script language="JavaScript">
  137 
  138   var flash;
  139   function getFlashMovie(appletName) {
  140       var isIE = navigator.appName.indexOf("Microsoft") != -1;
  141       var obj = (isIE) ? window[appletName] : window.document[appletName];
  142       //return window.document[appletName];
  143       if (obj.name = appletName) {
  144           return( obj );
  145       } else {
  146          alert ("can't find applet " + appletName);
  147       }
  148    }
  149 
  150   function submitAction() {
  151     getQE("$returnFieldName").value = getFlashMovie("$appletId").$submitAction();
  152    }
  153   function initialize() {
  154       getFlashMovie("$appletId").$initializeAction("$base64_xmlString");
  155   }
  156     function getQE(name1) { // get Question Element in problemMainForm by name
  157         var isIE = navigator.appName.indexOf("Microsoft") != -1;
  158       var obj = (isIE) ? document.getElementById(name1)
  159                           :document.problemMainForm[name1];
  160       // needed for IE -- searches id and name space so it can be unreliable if names are not unique
  161       if (obj.name = name1 ) {
  162         return( obj );
  163       } else {
  164         alert("Can't find " + name1);
  165         listQuestionElements();
  166       }
  167 
  168     }
  169     function getQuestionElement(name1) {
  170       return getQE(name1);
  171     }
  172 
  173     function listQuestionElements() { // list all HTML elements in main problem form
  174        var isIE = navigator.appName.indexOf("Microsoft") != -1;
  175        var mainForm =  (isIE) ?  document.getElementsByTagName("input") : document.getElementsByTagName("input");
  176        var str=mainForm.length +" Question Elements\n type | name = value  < id > \n";
  177        for( var i=0; i< mainForm.length; i++) {
  178            str = str + " "+i+" " + mainForm[i].type
  179                            + " | " + mainForm[i].name
  180                            + "= " + mainForm[i].value +
  181                            " <" + mainForm[i].id + ">\n";
  182        }
  183        alert(str +"\n Place listQuestionElements() at end of document in order to get all form elements!");
  184    }
  185 
  186 
  187     </script>
  188 
  189 END_HEADER_SCRIPT
  190 
  191 
  192 #   <object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0"
  193 #            width="550" height="400" id="$appletId" align="middle">
  194 #       <param name="allowScriptAccess" value="sameDomain" />
  195 #       <param name="allowFullScreen" value="false" />
  196 #       <param name="movie" value="$appletName.swf" />
  197 #       <param name="quality" value="high" />
  198 #       <param name="bgcolor" value="#ffffcc" />
  199 #       <embed src="$codebase/$appletName.swf" quality="high" bgcolor="#ffffcc" width="550" height="400" name="$appletName"
  200 #          align="middle"  id="$appletId",
  201 #          align="middle" allowScriptAccess="sameDomain"
  202 #          allowFullScreen="false"
  203 #         type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" />
  204 #         <param name="quality" value="high" /><param name="bgcolor" value="#ffffcc" />
  205 #     </object>
  206 
  207 =pod
  208 
  209 The secret to making this applet work with IE in addition to normal browsers
  210 is the addition of the C(<form></form>) construct just before the object.
  211 
  212 For some reason IE has trouble locating a flash object which is contained
  213 within a form.  Adding this second blank form with the larger problemMainForm
  214 seems to solve the problem.
  215 
  216 This follows method2 of the advice given in url(http://kb.adobe.com/selfservice/viewContent.do?externalId=kb400730&sliceId=2)
  217 Method1 and methods involving SWFObject(Geoff Stearns) and SWFFormFix (Steve Kamerman) have yet to be fully investigated:
  218 http://devel.teratechnologies.net/swfformfix/swfobject_swfformfix_source.js
  219 http://www.teratechnologies.net/stevekamerman/index.php?m=01&y=07&entry=entry070101-033933
  220 
  221   use constant DEFAULT_OBJECT_TEXT =><<'END_OBJECT_TEXT';
  222     <form></form>
  223     <object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
  224          id="$appletName" width="500" height="375"
  225          codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab">
  226        <param name="movie" value="$codebase/$appletName.swf" />
  227        <param name="quality" value="high" />
  228        <param name="bgcolor" value="#869ca7" />
  229        <param name="allowScriptAccess" value="sameDomain" />
  230        <embed src="$codebase/$appletName.swf" quality="high" bgcolor="#869ca7"
  231          width="550" height="400" name="$appletName" align="middle" id="$appletID"
  232          play="true" loop="false" quality="high" allowScriptAccess="sameDomain"
  233          type="application/x-shockwave-flash"
  234          pluginspage="http://www.macromedia.com/go/getflashplayer">
  235        </embed>
  236 
  237      </object>
  238   END_OBJECT_TEXT
  239 
  240 =cut
  241 
  242 use constant DEFAULT_OBJECT_TEXT =><<'END_OBJECT_TEXT';
  243   <form></form>
  244   <object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
  245              id="$appletName" width="500" height="375"
  246              codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab">
  247          <param name="movie" value="$codebase/$appletName.swf" />
  248          <param name="quality" value="high" />
  249          <param name="bgcolor" value="#869ca7" />
  250          <param name="allowScriptAccess" value="sameDomain" />
  251          <embed src="$codebase/$appletName.swf" quality="high" bgcolor="#869ca7"
  252              width="550" height="400" name="$appletName" align="middle" id="$appletID"
  253              play="true" loop="false" quality="high" allowScriptAccess="sameDomain"
  254              type="application/x-shockwave-flash"
  255              pluginspage="http://www.macromedia.com/go/getflashplayer">
  256          </embed>
  257 
  258      </object>
  259 END_OBJECT_TEXT
  260 
  261 
  262 sub new {
  263    my $class = shift;
  264    my $self = {
  265     host =>'',
  266     port => '',
  267     path => '',
  268     appletName =>'',
  269     codebase=>'',
  270     appletId  =>'',
  271     params    =>undef,
  272     base64_xmlString => 'foobar',
  273     initializeActionAlias => 'setupProblem',
  274     submitActionAlias  => 'checkAnswer',
  275     returnFieldName    => 'receivedField',
  276     headerText   => DEFAULT_HEADER_TEXT(),
  277     objectText   => DEFAULT_OBJECT_TEXT(),
  278     @_,
  279   };
  280   bless $self, $class;
  281   #$self -> _initialize(@_);
  282   return $self;
  283 }
  284 
  285 sub  header {
  286   my $self = shift;
  287   if ($_[0] eq "reset") {  # $applet->header('reset');  erases default header text.
  288     $self->{headerText}='';
  289   } else {
  290     $self->{headerText} .= join("",@_);  # $applet->header(new_text); concatenates new_text to existing header.
  291   }
  292     $self->{headerText};
  293 }
  294 sub  object {
  295   my $self = shift;
  296   if ($_[0] eq "reset") {
  297     $self->{objectText}='';
  298   } else {
  299     $self->{objectText} .= join("",@_);
  300   }
  301     $self->{objectText};
  302 }
  303 sub params {
  304   my $self = shift;
  305   if (ref($_[0]) =~/HASH/) {
  306     $self->{params} = shift;
  307   } elsif ( $_[0] =~ '') {
  308     # do nothing (read)
  309   } else {
  310     warn "You must enter a reference to a hash for the parameter list";
  311   }
  312   $self->{params};
  313 }
  314 
  315 sub initializeActionAlias {
  316   my $self = shift;
  317   $self->{initializeActionAlias} = shift ||$self->{initializeActionAlias}; # replace the current contents if non-empty
  318     $self->{initializeActionAlias};
  319 }
  320 
  321 sub submitActionAlias {
  322   my $self = shift;
  323   $self->{submitActionAlias} = shift ||$self->{submitActionAlias}; # replace the current contents if non-empty
  324     $self->{submitActionAlias};
  325 }
  326 sub returnFieldName {
  327   my $self = shift;
  328   $self->{returnFieldName} = shift ||$self->{returnFieldName}; # replace the current contents if non-empty
  329     $self->{returnFieldName};
  330 }
  331 sub codebase {
  332   my $self = shift;
  333   $self->{codebase} = shift ||$self->{codebase}; # replace the current codebase if non-empty
  334     $self->{codebase};
  335 }
  336 sub appletName {
  337   my $self = shift;
  338   $self->{appletName} = shift ||$self->{appletName}; # replace the current appletName if non-empty
  339     $self->{appletName};
  340 }
  341 sub appletId {
  342   my $self = shift;
  343   $self->{appletId} = shift ||$self->{appletId}; # replace the current appletName if non-empty
  344     $self->{appletId};
  345 }
  346 sub xmlString {
  347   my $self = shift;
  348   my $str = shift;
  349   $self->{base64_xmlString} =  encode_base64($str)   ||$self->{base64_xmlString}; # replace the current string if non-empty
  350   $self->{base64_xmlString} =~ s/\n//g;
  351     decode_base64($self->{base64_xmlString});
  352 }
  353 
  354 sub base64_xmlString{
  355   my $self = shift;
  356   $self->{base64_xmlString} = shift ||$self->{base64_xmlString}; # replace the current string if non-empty
  357     $self->{base64_xmlString};
  358 }
  359 
  360 #FIXME
  361 # need to be able to adjust header material
  362 
  363 sub insertHeader {
  364     my $self = shift;
  365     my $codebase = $self->{codebase};
  366     my $appletId = $self->{appletId};
  367     my $appletName = $self->{appletName};
  368     my $base64_xmlString = $self->{base64_xmlString};
  369     my $initializeAction = $self->{initializeActionAlias};
  370     my $submitAction = $self->{submitActionAlias};
  371     my $returnFieldName= $self->{returnFieldName};
  372     my $headerText = $self->header();
  373     $headerText =~ s/(\$\w+)/$1/gee;   # interpolate variables p17 of Cookbook
  374 
  375     return $headerText;
  376 
  377 
  378 }
  379 
  380 
  381 # <script language="javascript">
  382 #   if (AC_FL_RunContent == 0) {
  383 #     alert("This page requires AC_RunActiveContent.js.");
  384 #   } else {
  385 #     AC_FL_RunContent(
  386 #       'codebase', 'http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0',
  387 #       'width', '100%',
  388 #       'height', '100%',
  389 #       'src', 'http://$codebase/$appletName',
  390 #       'quality', 'high',
  391 #       'pluginspage', 'http://www.macromedia.com/go/getflashplayer',
  392 #       'align', 'middle',
  393 #       'play', 'true',
  394 #       'loop', 'true',
  395 #       'scale', 'showall',
  396 #       'wmode', 'window',
  397 #       'devicefont', 'false',
  398 #       'id', '$appletId',
  399 #       'bgcolor', '#ffffcc',
  400 #       'name', '$appletName',
  401 #       'menu', 'true',
  402 #       'allowFullScreen', 'false',
  403 #       'allowScriptAccess','sameDomain',
  404 #       'movie', '$appletName',
  405 #       'salign', ''
  406 #       ); //end AC code
  407 #   }
  408 # </script>
  409 sub insertObject {
  410     my $self = shift;
  411     my $codebase = $self->{codebase};
  412     my $appletId = $self->{appletId};
  413     my $appletName = $self->{appletName};
  414     $codebase = findAppletCodebase("$appletName.swf") unless $codebase;
  415     $objectText = $self->{objectText};
  416     $objectText =~ s/(\$\w+)/$1/gee;
  417     return $objectText;
  418 }
  419 
  420 sub initialize  {
  421     my $self = shift;
  422   return q{
  423     <script>
  424       initialize();
  425       // this should really be done in the <body> tag
  426     </script>
  427   };
  428 
  429 }
  430 
  431 1;

aubreyja at gmail dot com
ViewVC Help
Powered by ViewVC 1.0.9