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