Parent Directory
|
Revision Log
added alignedChoice.pl from the Union collection of macros updated POD documentation.
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.24 2010/01/03 17:13:46 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 See also L<http://webwork.maa.org/pod/pg_TRUNK/lib/Applet.html>. 30 31 =cut 32 33 ######################################################################### 34 # 35 # Add basic functionality to the header of the question 36 # 37 # don't reload this file 38 ######################################################################### 39 40 sub _AppletObjects_init{ 41 42 main::HEADER_TEXT(<<'END_HEADER_TEXT'); 43 <script language="javascript">AC_FL_RunContent = 0;</script> 44 <script src="/webwork2_files/applets/AC_RunActiveContent.js" language="javascript"> 45 </script> 46 <script src="/webwork2_files/js/Base64.js" language="javascript"> 47 </script> 48 <script src="/webwork2_files/js/ww_applet_support.js" language="javascript"> 49 //upload functions stored in /opt/webwork/webwork2/htdocs/js ... 50 </script> 51 END_HEADER_TEXT 52 53 }; 54 55 =head3 FlashApplet 56 57 Useage: $applet = FlashApplet(); 58 59 =cut 60 61 sub FlashApplet { 62 return new FlashApplet(@_); 63 64 } 65 66 =head3 JavaApplet 67 68 Useage: $applet = JavaApplet( 69 70 71 ); 72 73 =cut 74 75 sub JavaApplet { 76 return new JavaApplet(@_); 77 78 } 79 80 =head3 CanvasApplet 81 82 Useage: $applet = CanvasApplet( 83 84 85 ); 86 87 =cut 88 89 sub CanvasApplet { 90 return new CanvasApplet(@_); 91 } 92 package Applet; 93 94 95 96 =head1 Methods 97 98 =cut 99 100 ## this method is defined in this file 101 ## because the main subroutines HEADER_TEXT and MODES are 102 ## not available to the module FlashApplet when that file 103 ## is compiled (at the time the apache child process is first initialized) 104 105 =head3 insertAll 106 107 Useage: TEXT( $applet->insertAll() ); 108 \{ $applet->insertAll() \} (used within BEGIN_TEXT/END_TEXT blocks) 109 110 =cut 111 112 =pod 113 114 Inserts applet at this point in the HTML code. (In TeX mode a message "Applet" is written.) This method 115 also adds the applets header material into the header portion of the HTML page. It effectively inserts 116 the outputs of both C<$applet-E<gt>insertHeader> and C<$applet-E<gt>insertObject> (defined in L<Applet.pm> ) 117 in the appropriate places. In addition it creates a hidden answer blank for storing the state of the applet 118 and provides mechanisms for revealing the state while debugging the applet. 119 120 Note: This method is defined here rather than in Applet.pl because it 121 requires access to the RECORD_FORM_LABEL subroutine 122 and to the routine accessing the stored values of the answers. These are defined in main::. 123 FIXME -- with the creation of the PGcore object this can now be rewritten 124 125 =cut 126 127 sub insertAll { ## inserts both header text and object text 128 my $self = shift; 129 my %options = @_; 130 131 132 ########################## 133 # determine debug mode 134 # debugMode can be turned on by setting it to 1 in either the applet definition or at insertAll time 135 ########################## 136 137 my $debugMode = (defined($options{debug}) and $options{debug}>0) ? $options{debug} : 0; 138 my $includeAnswerBox = (defined($options{includeAnswerBox}) and $options{includeAnswerBox}==1) ? 1 : 0; 139 $debugMode = $debugMode || $self->debugMode; 140 $self->debugMode( $debugMode); 141 142 143 my $reset_button = $options{reinitialize_button} || 0; 144 warn qq! please change "reset_button=>1" to "reinitialize_button=>1" in the applet->installAll() command \n! if defined($options{reset_button}); 145 146 ########################## 147 # Get data to be interpolated into the HTML code defined in this subroutine 148 # 149 # This consists of the name of the applet and the names of the routines 150 # to get and set State of the applet (which is done every time the question page is refreshed 151 # and to get and set Config which is the initial configuration the applet is placed in 152 # when the question is first viewed. It is also the state which is returned to when the 153 # reset button is pressed. 154 ########################## 155 156 # prepare html code for storing state 157 my $appletName = $self->appletName; 158 my $appletStateName = "${appletName}_state"; # the name of the hidden "answer" blank storing state FIXME -- use persistent data instead 159 my $getState = $self->getStateAlias; # names of routines for this applet 160 my $setState = $self->setStateAlias; 161 my $getConfig = $self->getConfigAlias; 162 my $setConfig = $self->setConfigAlias; 163 164 my $base64_initialState = encode_base64($self->initialState); 165 main::RECORD_FORM_LABEL($appletStateName); #this insures that the state will be saved from one invocation to the next 166 # FIXME -- with PGcore the persistant data mechanism can be used instead 167 my $answer_value = ''; 168 169 ########################## 170 # implement the sticky answer mechanism for maintaining the applet state when the question page is refreshed 171 # This is important for guest users for whom no permanent record of answers is recorded. 172 ########################## 173 174 if ( defined( ${$main::inputs_ref}{$appletStateName} ) and ${$main::inputs_ref}{$appletStateName} =~ /\S/ ) { 175 $answer_value = ${$main::inputs_ref}{$appletStateName}; 176 } elsif ( defined( $main::rh_sticky_answers->{$appletStateName} ) ) { 177 warn "type of sticky answers is ", ref( $main::rh_sticky_answers->{$appletStateName} ); 178 $answer_value = shift( @{ $main::rh_sticky_answers->{$appletStateName} }); 179 } 180 $answer_value =~ tr/\\$@`//d; #`## make sure student answers can not be interpolated by e.g. EV3 181 $answer_value =~ s/\s+/ /g; ## remove excessive whitespace from student answer 182 183 ########################## 184 # insert a hidden answer blank to hold the applet's state 185 # (debug =>1 makes it visible for debugging and provides debugging buttons) 186 ########################## 187 188 189 ########################## 190 # Regularize the applet's state -- which could be in either XML format or in XML format encoded by base64 191 # In rare cases it might be simple string -- protect against that by putting xml tags around the state 192 # The result: 193 # $base_64_encoded_answer_value -- a base64 encoded xml string 194 # $decoded_answer_value -- and xml string 195 ########################## 196 197 my $base_64_encoded_answer_value; 198 my $decoded_answer_value; 199 if ( $answer_value =~/<XML|<?xml/i) { 200 $base_64_encoded_answer_value = encode_base64($answer_value); 201 $decoded_answer_value = $answer_value; 202 } else { 203 $decoded_answer_value = decode_base64($answer_value); 204 if ( $decoded_answer_value =~/<XML|<?xml/i) { # great, we've decoded the answer to obtain an xml string 205 $base_64_encoded_answer_value = $answer_value; 206 } else { #WTF?? apparently we don't have XML tags 207 $answer_value = "<xml>$answer_value</xml>"; 208 $base_64_encoded_answer_value = encode_base64($answer_value); 209 $decoded_answer_value = $answer_value; 210 } 211 } 212 $base_64_encoded_answer_value =~ s/\r|\n//g; # get rid of line returns 213 214 ########################## 215 # Construct answer blank for storing state -- in both regular (answer blank hidden) 216 # and debug (answer blank displayed) modes. 217 ########################## 218 219 ########################## 220 # debug version of the applet state answerBox and controls (all displayed) 221 # stored in 222 # $debug_input_element 223 ########################## 224 225 # my $debug_input_element = qq!\n<textarea rows="4" cols="80" 226 # name = "$appletStateName" id = "$appletStateName">$decoded_answer_value</textarea><br/>!; 227 # conversion to base64 is now being done in the setState module 228 # when submitting we want everything to be in the base64 mode for safety 229 my $debug_input_element = qq!\n<textarea rows="4" cols="80" 230 name = "$appletStateName" id = "$appletStateName">$answer_value</textarea><br/>!; 231 232 if ($getState=~/\S/) { # if getStateAlias is not an empty string 233 $debug_input_element .= qq! 234 <input type="button" value="$getState" 235 onClick=" debugText=''; 236 ww_applet_list['$appletName'].getState() ; 237 if (debugText) {alert(debugText)};" 238 />!; 239 } 240 if ($setState=~/\S/) { # if setStateAlias is not an empty string 241 $debug_input_element .= qq! 242 <input type="button" value="$setState" 243 onClick="debugText=''; 244 ww_applet_list['$appletName'].setState(); 245 if (debugText) {alert(debugText)};" 246 />!; 247 } 248 if ($getConfig=~/\S/) { # if getConfigAlias is not an empty string 249 $debug_input_element .= qq! 250 <input type="button" value="$getConfig" 251 onClick="debugText=''; 252 ww_applet_list['$appletName'].getConfig(); 253 if (debugText) {alert(debugText)};" 254 />!; 255 } 256 if ($setConfig=~/\S/) { # if setConfigAlias is not an empty string 257 $debug_input_element .= qq! 258 <input type="button" value="$setConfig" 259 onClick="debugText=''; 260 ww_applet_list['$appletName'].setConfig(); 261 if (debugText) {alert(debugText)};" 262 />!; 263 } 264 265 ########################## 266 # Construct answerblank for storing state 267 # using either the debug version (defined above) or the non-debug version 268 # where the state variable is hidden and the definition is very simple 269 # stored in 270 # $state_input_element 271 ########################## 272 273 my $state_input_element = ($debugMode) ? $debug_input_element : 274 qq!\n<input type="hidden" name = "$appletStateName" id = "$appletStateName" value ="$base_64_encoded_answer_value">!; 275 276 ########################## 277 # Construct the reset button string (this is blank if the button is not to be displayed 278 # $reset_button_str 279 ########################## 280 281 my $reset_button_str = ($reset_button) ? 282 qq!<input type='submit' name='previewAnswers' id ='previewAnswers' value='return this question to its initial state' 283 onClick="setHTMLAppletStateToRestart('$appletName')"><br/>! 284 : '' ; 285 286 ########################## 287 # Combine the state_input_button and the reset button into one string 288 # $state_storage_html_code 289 ########################## 290 291 292 $state_storage_html_code = qq!<input type="hidden" name="previous_$appletStateName" id = "previous_$appletStateName" value = "$base_64_encoded_answer_value">! 293 . $state_input_element. $reset_button_str 294 ; 295 ########################## 296 # Construct the answerBox (if it is requested). This is a default input box for interacting 297 # with the applet. It is separate from maintaining state but it often contains similar data. 298 # Additional answer boxes or buttons can be defined but they must be explicitly connected to 299 # the applet with additional javaScript commands. 300 # Result: $answerBox_code 301 ########################## 302 303 my $answerBox_code =''; 304 if ($includeAnswerBox) { 305 if ($debugMode) { 306 307 $answerBox_code = $main::BR . main::NAMED_ANS_RULE('answerBox', 50 ); 308 $answerBox_code .= qq! 309 <br/><input type="button" value="get Answer from applet" onClick="eval(ww_applet_list['$appletName'].submitActionScript )"/> 310 <br/> 311 !; 312 } else { 313 $answerBox_code = main::NAMED_HIDDEN_ANS_RULE('answerBox', 50 ); 314 } 315 } 316 317 ########################## 318 # insert header material 319 ########################## 320 main::HEADER_TEXT($self->insertHeader()); 321 # update the debug mode for this applet. 322 main::HEADER_TEXT(qq!<script language="javascript"> ww_applet_list["$appletName"].debugMode = $debugMode;\n</script>!); 323 324 ########################## 325 # Return HTML or TeX strings to be included in the body of the page 326 ########################## 327 328 return main::MODES(TeX=>' {\bf applet } ', HTML=>$self->insertObject.$main::BR.$state_storage_html_code.$answerBox_code); 329 } 330 331 =head3 Example problem 332 333 334 =cut 335 336 337 338 =pod 339 340 341 DOCUMENT(); 342 343 # Load whatever macros you need for the problem 344 loadMacros("PG.pl", 345 "PGbasicmacros.pl", 346 "PGchoicemacros.pl", 347 "PGanswermacros.pl", 348 "AppletObjects.pl", 349 "MathObjects.pl", 350 "source.pl" 351 ); 352 353 ## Do NOT show partial correct answers 354 $showPartialCorrectAnswers = 0; 355 356 357 358 ################################### 359 # Create link to applet 360 ################################### 361 362 $applet = FlashApplet(); 363 my $appletName = "ExternalInterface"; 364 $applet->codebase(findAppletCodebase("$appletName.swf")); 365 $applet->appletName($appletName); 366 $applet->appletId($appletName); 367 368 # findAppletCodebase looks for the applet in a list 369 # of locations specified in global.conf 370 371 ################################### 372 # Add additional javaScript functions to header section of HTML to 373 # communicate with the "ExternalInterface" applet. 374 ################################### 375 376 $applet->header(<<'END_HEADER'); 377 <script language="javascript" src="https://devel.webwork.rochester.edu:8002/webwork2_files/js/BrowserSniffer.js"> 378 </script> 379 380 381 <script language="JavaScript"> 382 function getBrowser() { 383 //alert("look for sniffer"); 384 var sniffer = new BrowserSniffer(); 385 //alert("found sniffer" +sniffer); 386 return sniffer; 387 } 388 389 function updateStatus(sMessage) { 390 getQE("playbackStatus").value = sMessage; 391 } 392 393 function newColor() { 394 395 getApplet("ExternalInterface").updateColor(Math.round(Math.random() * 0xFFFFFF)); 396 } 397 398 </script> 399 END_HEADER 400 401 ################################### 402 # Configure applet 403 ################################### 404 405 # not used here. Allows for uploading an xml string for the applet 406 407 408 409 410 ################################### 411 # write the text for the problem 412 ################################### 413 414 TEXT(beginproblem()); 415 416 417 418 BEGIN_TEXT 419 \{ $applet->insertAll() \} 420 $PAR 421 422 The Flash object operates above this line. The box and button below this line are part of 423 the WeBWorK problem. They communicate with the Flash object. 424 $HR 425 Status <input type="text" id="playbackStatus" value="started" /><br /> 426 Color <input type="button" value="new color" name="newColorButton" onClick="newColor()" /> 427 $PAR $HR 428 This flash applet was created by Barbara Kaskosz. 429 430 END_TEXT 431 432 ENDDOCUMENT(); 433 434 435 436 437 =cut
aubreyja at gmail dot com | ViewVC Help |
Powered by ViewVC 1.0.9 |