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