From: Mike G. v. a. <we...@ma...> - 2008-03-16 14:52:46
|
Log Message: ----------- New version of Applet.pm and AppletObjects.pl that supports both flash new FlashApplet(); and java applets new JavaApplet(); see pod docs in those two files for more details. Modified Files: -------------- pg/macros: AppletObjects.pl Revision Data ------------- Index: AppletObjects.pl =================================================================== RCS file: /webwork/cvs/system/pg/macros/AppletObjects.pl,v retrieving revision 1.3 retrieving revision 1.4 diff -Lmacros/AppletObjects.pl -Lmacros/AppletObjects.pl -u -r1.3 -r1.4 --- macros/AppletObjects.pl +++ macros/AppletObjects.pl @@ -16,7 +16,7 @@ =head1 NAME -AppletOjects.pl - Macro-based front end for the Applet.pm module. +AppletObjects.pl - Macro-based front end for the Applet.pm module. =head1 DESCRIPTION @@ -32,7 +32,116 @@ =cut -sub _PGapplets_init {}; # don't reload this file + +sub _AppletObjects_init{}; # don't reload this file + + +main::HEADER_TEXT(<<'END_HEADER_TEXT'); + <script language="javascript">AC_FL_RunContent = 0;</script> + <script src="/webwork2_files/applets/AC_RunActiveContent.js" language="javascript"> + </script> + <script src="/webwork2_files/js/Base64.js" language="javascript"> + </script> + +<script language="JavaScript"> + var applet_initializeAction_list = new Object; + var applet_submitAction_list = new Object; + var applet_setState_list = new Object; + var applet_getState_list = new Object; + var applet_config_list = new Object; + + + function base64Q(str) { + return !str.match(/<XML>*/i); + } + + function submitAction() { + //alert("submit Action" ); + for (var applet in applet_submitAction_list) { + //alert(applet); + applet_submitAction_list[applet](); + } + + } + // Give some time delay before initializing + function initializeAction() { + //alert("ready to initialize"); + // give some delay to allow flash applet to load. FIXME + window.setTimeout("initializeAction1()",200); + //initializeAction1(); + } + function initializeAction1() { + + for (var appletName in applet_initializeAction_list) { + //alert("initialize: " + appletName); + try{ + applet_config_list[appletName](); + } catch(e) { + alert("unable to configure " + appletName + " It may have been slow to load. " +e ); + } + try{ + applet_initializeAction_list[appletName](); + } catch(e) { + alert("unable to initialize " + appletName + " It may have been slow to load. " +e ); + } + } + } + + + var flash; + function getApplet(appletName) { + var isIE = navigator.appName.indexOf("Microsoft") != -1; + var obj = (isIE) ? window[appletName] : window.document[appletName]; + //return window.document[appletName]; + if (obj && (obj.name = appletName)) { + return( obj ); + } else { + alert ("can't find applet " + appletName); + } + } + + function listQuestionElements() { // list all HTML input and textarea elements in main problem form + var isIE = navigator.appName.indexOf("Microsoft") != -1; + var elementList = (isIE) ? document.getElementsByTagName("input") : document.problemMainForm.getElementsByTagName("input"); + var str=elementList.length +" Question Elements\n type | name = value < id > \n"; + for( var i=0; i< elementList.length; i++) { + str = str + " "+i+" " + elementList[i].type + + " | " + elementList[i].name + + "= " + elementList[i].value + + " <" + elementList[i].id + ">\n"; + } + elementList = (isIE) ? document.getElementsByTagName("textarea") : document.problemMainForm.getElementsByTagName("textarea"); + for( var i=0; i< elementList.length; i++) { + str = str + " "+i+" " + elementList[i].type + + " | " + elementList[i].name + + "= " + elementList[i].value + + " <" + elementList[i].id + ">\n"; + } + alert(str +"\n Place listQuestionElements() at end of document in order to get all form elements!"); + } + + function getQE(name1) { // get Question Element in problemMainForm by name + var isIE = navigator.appName.indexOf("Microsoft") != -1; + var obj = (isIE) ? document.getElementById(name1) + :document.problemMainForm[name1]; + // needed for IE -- searches id and name space so it can be unreliable if names are not unique + if (!obj || obj.name != name1) { + alert("Can't find element " + name1); + listQuestionElements(); + } else { + return( obj ); + } + + } + function getQuestionElement(name1) { + return getQE(name1); + } + + </script> + +END_HEADER_TEXT + + =head3 FlashApplet @@ -46,8 +155,15 @@ } -package FlashApplet; +sub JavaApplet { + return new JavaApplet(@_); + +} + +package Applet; + + =head2 Methods =cut @@ -57,10 +173,10 @@ ## not available to the module FlashApplet when that file ## is compiled (at the time the apache child process is first initialized) -=head3 insert +=head3 insertAll - Useage: TEXT( $applet->insert() ); - \{ $applet->insert \} (used within BEGIN_TEXT/END_TEXT blocks) + Useage: TEXT( $applet->insertAll() ); + \{ $applet->insertAll() \} (used within BEGIN_TEXT/END_TEXT blocks) =cut @@ -68,17 +184,70 @@ Inserts applet at this point in the HTML code. (In TeX mode a message "Applet" is written.) This method also adds the applets header material into the header portion of the HTML page. It effectively inserts -the outputs of both C<$applet-E<gt>insertHeader> and C<$applet-E<gt>insertObject> (defined in L<Applet.pm> ) in the appropriate places. +the outputs of both C<$applet-E<gt>insertHeader> and C<$applet-E<gt>insertObject> (defined in L<Applet.pm> ) +in the appropriate places. + +Note: This method is defined here rather than in Applet.pl because it + requires access to the RECORD_FORM_LABEL subroutine + and to the routine accessing the stored values of the answers. These are defined in main::. =cut -sub insert { ## inserts both header text and object text +sub insertAll { ## inserts both header text and object text my $self = shift; + my %options = @_; + $self->debug( (defined($options{debug}) and $options{debug}==1) ? 1 : 0 ); + my $reset_button = $options{reset_button} || 0; + # prepare html code for storing state + my $appletName = $self->appletName; + my $appletStateName = "${appletName}_state"; + my $getState = $self->getStateAlias; + my $setState = $self->setStateAlias; + my $base64_initialState = $self->base64_state; + main::RECORD_FORM_LABEL($appletStateName); #this insures that they'll be saved from one invocation to the next + #main::RECORD_FORM_LABEL("previous_$appletStateName"); + my $answer_value = ''; + $answer_value = ${$main::inputs_ref}{$appletStateName} if defined(${$main::inputs_ref}{$appletStateName}); + + if ( defined( $main::rh_sticky_answers->{$appletStateName} ) ) { + $answer_value = shift( @{ $main::rh_sticky_answers->{$appletStateName} }); + $answer_value = '' unless defined($answer_value); + } + $answer_value =~ tr/\\$@`//d; #`## make sure student answers can not be interpolated by e.g. EV3 + $answer_value =~ s/\s+/ /g; ## remove excessive whitespace from student answer + + ####### + # insert a hidden variable to hold the applet's state (debug =>1 makes it visible for debugging and provides debugging buttons) + ####### + my $base_64_encoded_answer_value = ($answer_value =~/<XML>/i)? encode_base64($answer_value) : $answer_value; + my $decoded_answer_value = ($answer_value =~/<XML>/i) ? $answer_value : decode_base64($answer_value); + my $debug_input_element = qq!\n<textarea rows="4" cols="80" + name = "$appletStateName">$decoded_answer_value</textarea><br/> + <input type="button" value="getState" + onClick="applet_getState_list['$appletName']()"> + <input type="button" value="setState" + onClick="applet_setState_list['$appletName'](); + var tmp = getQE('$appletStateName').value;"> + !; + my $state_input_element = ($self->debug == 1) ? $debug_input_element : + qq!\n<input type="hidden" name = "$appletStateName" value ="$base_64_encoded_answer_value">!; + my $reset_button_str = ($reset_button) ? + qq!<br/><input type='button' value='reset applet' onClick="applet_setState_list['$appletName']('<xml></xml>')">! + : '' + ; + # always base64 encode the hidden answer value to prevent problems with quotes. + # + $state_storage_html_code = + $reset_button_str. + $state_input_element. + qq!<input type="hidden" name="previous_$appletStateName" value = "$base_64_encoded_answer_value">!; + ####### + # insert header material + ####### main::HEADER_TEXT($self->insertHeader()); - return main::MODES(TeX=>' {\bf flash applet } ', HTML=>$self->insertObject); + return main::MODES(TeX=>' {\bf applet } ', HTML=>$self->insertObject.$main::BR.$state_storage_html_code); } - =head3 Example problem @@ -120,7 +289,7 @@ # of locations specified in global.conf ################################### - # Add java script functions to header section of HTML to + # Add additional javaScript functions to header section of HTML to # communicate with the "ExternalInterface" applet. ################################### @@ -138,27 +307,14 @@ } function updateStatus(sMessage) { - //alert("update form with " + sMessage); - //window.document.problemMainForm.playbackStatus.value = sMessage; - //document.problemMainForm.playbackStatus.value = sMessage; - document.getElementById("playbackStatus").value = sMessage; + getQE("playbackStatus").value = sMessage; } function newColor() { - //var app = getFlashMovie("ExternalInterface").getElementById("movie1"); - // alert(app); - // The difficult issue in adapting Barbara's original file was locating - // the object. It took several tries to find a method that worked - // and it is quite likely that it will not work in all browsers. - - //alert("update color"); - //alert(getFlashMovie("ExternalInterface")); - getFlashMovie("ExternalInterface").updateColor(Math.round(Math.random() * 0xFFFFFF)); + + getApplet("ExternalInterface").updateColor(Math.round(Math.random() * 0xFFFFFF)); } - function submitAction() { newColor() - } - </script> END_HEADER @@ -178,17 +334,9 @@ TEXT(beginproblem()); - TEXT( MODES(TeX=>'object code', HTML=><<END_SCRIPT ) ); - <script> - //alert("foobar"); - initialize(); - // this should really be done in the <body> tag -- can we make that happen? - </script> - END_SCRIPT - BEGIN_TEXT - \{ $applet->insert \} + \{ $applet->insertAll() \} $PAR The Flash object operates above this line. The box and button below this line are part of |