[system] / trunk / pg / macros / AppletObjects.pl Repository:
ViewVC logotype

Annotation of /trunk/pg/macros/AppletObjects.pl

Parent Directory Parent Directory | Revision Log Revision Log


Revision 6372 - (view) (download) (as text)

1 : gage 5582 ################################################################################
2 :     # WeBWorK Online Homework Delivery System
3 :     # Copyright 2000-2007 The WeBWorK Project, http://openwebwork.sf.net/
4 : gage 6210 # $CVSHeader: pg/macros/AppletObjects.pl,v 1.24 2010/01/03 17:13:46 gage Exp $
5 : gage 5582 #
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 : gage 5618 AppletObjects.pl - Macro-based front end for the Applet.pm module.
20 : gage 5582
21 :    
22 :     =head1 DESCRIPTION
23 :    
24 :     This subroutines in this
25 : gage 5971 file provide mechanisms to insert Flash applets (and Java applets)
26 : gage 5582 into a WeBWorK problem.
27 :    
28 :    
29 :     =head1 SEE ALSO
30 :    
31 :     L<Applets.pm>.
32 :    
33 :     =cut
34 :    
35 : gage 5667 #########################################################################
36 :     #
37 :     # Add basic functionality to the header of the question
38 :     #
39 :     # don't reload this file
40 :     #########################################################################
41 : gage 5582
42 : gage 6026 sub _AppletObjects_init{
43 : gage 5618
44 :     main::HEADER_TEXT(<<'END_HEADER_TEXT');
45 :     <script language="javascript">AC_FL_RunContent = 0;</script>
46 :     <script src="/webwork2_files/applets/AC_RunActiveContent.js" language="javascript">
47 :     </script>
48 :     <script src="/webwork2_files/js/Base64.js" language="javascript">
49 : gage 5993 </script>
50 : gage 6316 <script src="/webwork2_files/js/ww_applet_support.js" language="javascript">
51 : gage 5993 //upload functions stored in /opt/webwork/webwork2/htdocs/js ...
52 : gage 5996 </script>
53 : gage 5618 END_HEADER_TEXT
54 :    
55 : gage 5667 };
56 : gage 5618
57 : gage 5582 =head3
58 :     FlashApplet
59 :    
60 :     Useage: $applet = FlashApplet();
61 :    
62 :     =cut
63 :    
64 :     sub FlashApplet {
65 : gage 5597 return new FlashApplet(@_);
66 : gage 5582
67 :     }
68 :    
69 : gage 5618 sub JavaApplet {
70 :     return new JavaApplet(@_);
71 : gage 5582
72 : gage 5618 }
73 :    
74 : gage 6297 sub CanvasApplet {
75 :     return new CanvasApplet(@_);
76 :     }
77 : gage 5618 package Applet;
78 :    
79 :    
80 :    
81 : gage 5582 =head2 Methods
82 :    
83 :     =cut
84 :    
85 :     ## this method is defined in this file
86 :     ## because the main subroutines HEADER_TEXT and MODES are
87 :     ## not available to the module FlashApplet when that file
88 :     ## is compiled (at the time the apache child process is first initialized)
89 :    
90 : gage 5618 =head3 insertAll
91 : gage 5582
92 : gage 5618 Useage: TEXT( $applet->insertAll() );
93 :     \{ $applet->insertAll() \} (used within BEGIN_TEXT/END_TEXT blocks)
94 : gage 5582
95 :     =cut
96 :    
97 :     =pod
98 :    
99 :     Inserts applet at this point in the HTML code. (In TeX mode a message "Applet" is written.) This method
100 :     also adds the applets header material into the header portion of the HTML page. It effectively inserts
101 : gage 5618 the outputs of both C<$applet-E<gt>insertHeader> and C<$applet-E<gt>insertObject> (defined in L<Applet.pm> )
102 : gage 6297 in the appropriate places. In addition it creates a hidden answer blank for storing the state of the applet
103 :     and provides mechanisms for revealing the state while debugging the applet.
104 : gage 5582
105 : gage 5618 Note: This method is defined here rather than in Applet.pl because it
106 :     requires access to the RECORD_FORM_LABEL subroutine
107 :     and to the routine accessing the stored values of the answers. These are defined in main::.
108 : gage 6297 FIXME -- with the creation of the PGcore object this can now be rewritten
109 : gage 5618
110 : gage 5582 =cut
111 :    
112 : gage 5618 sub insertAll { ## inserts both header text and object text
113 : gage 5582 my $self = shift;
114 : gage 5618 my %options = @_;
115 : gage 6026
116 : gage 6297
117 :     ##########################
118 :     # determine debug mode
119 : gage 6026 # debugMode can be turned on by setting it to 1 in either the applet definition or at insertAll time
120 : gage 6297 ##########################
121 :    
122 : gage 6178 my $debugMode = (defined($options{debug}) and $options{debug}>0) ? $options{debug} : 0;
123 : gage 6030 my $includeAnswerBox = (defined($options{includeAnswerBox}) and $options{includeAnswerBox}==1) ? 1 : 0;
124 : gage 6026 $debugMode = $debugMode || $self->debugMode;
125 :     $self->debugMode( $debugMode);
126 :    
127 :    
128 : gage 6030 my $reset_button = $options{reinitialize_button} || 0;
129 : gage 6178 warn qq! please change "reset_button=>1" to "reinitialize_button=>1" in the applet->installAll() command \n! if defined($options{reset_button});
130 : gage 6297
131 :     ##########################
132 :     # Get data to be interpolated into the HTML code defined in this subroutine
133 :     #
134 :     # This consists of the name of the applet and the names of the routines
135 :     # to get and set State of the applet (which is done every time the question page is refreshed
136 :     # and to get and set Config which is the initial configuration the applet is placed in
137 :     # when the question is first viewed. It is also the state which is returned to when the
138 :     # reset button is pressed.
139 :     ##########################
140 :    
141 : gage 5618 # prepare html code for storing state
142 :     my $appletName = $self->appletName;
143 : gage 6297 my $appletStateName = "${appletName}_state"; # the name of the hidden "answer" blank storing state FIXME -- use persistent data instead
144 :     my $getState = $self->getStateAlias; # names of routines for this applet
145 : gage 5618 my $setState = $self->setStateAlias;
146 : gage 6019 my $getConfig = $self->getConfigAlias;
147 :     my $setConfig = $self->setConfigAlias;
148 :    
149 : gage 6030 my $base64_initialState = encode_base64($self->initialState);
150 : gage 6297 main::RECORD_FORM_LABEL($appletStateName); #this insures that the state will be saved from one invocation to the next
151 :     # FIXME -- with PGcore the persistant data mechanism can be used instead
152 : gage 5618 my $answer_value = '';
153 : gage 6297
154 :     ##########################
155 :     # implement the sticky answer mechanism for maintaining the applet state when the question page is refreshed
156 :     # This is important for guest users for whom no permanent record of answers is recorded.
157 :     ##########################
158 :    
159 : gage 5993 if ( defined( ${$main::inputs_ref}{$appletStateName} ) and ${$main::inputs_ref}{$appletStateName} =~ /\S/ ) {
160 :     $answer_value = ${$main::inputs_ref}{$appletStateName};
161 :     } elsif ( defined( $main::rh_sticky_answers->{$appletStateName} ) ) {
162 :     warn "type of sticky answers is ", ref( $main::rh_sticky_answers->{$appletStateName} );
163 : gage 5618 $answer_value = shift( @{ $main::rh_sticky_answers->{$appletStateName} });
164 :     }
165 :     $answer_value =~ tr/\\$@`//d; #`## make sure student answers can not be interpolated by e.g. EV3
166 :     $answer_value =~ s/\s+/ /g; ## remove excessive whitespace from student answer
167 : gage 6297
168 :     ##########################
169 :     # insert a hidden answer blank to hold the applet's state
170 :     # (debug =>1 makes it visible for debugging and provides debugging buttons)
171 :     ##########################
172 :    
173 :    
174 :     ##########################
175 :     # Regularize the applet's state -- which could be in either XML format or in XML format encoded by base64
176 :     # In rare cases it might be simple string -- protect against that by putting xml tags around the state
177 :     # The result:
178 :     # $base_64_encoded_answer_value -- a base64 encoded xml string
179 :     # $decoded_answer_value -- and xml string
180 :     ##########################
181 :    
182 : gage 5993 my $base_64_encoded_answer_value;
183 :     my $decoded_answer_value;
184 :     if ( $answer_value =~/<XML|<?xml/i) {
185 :     $base_64_encoded_answer_value = encode_base64($answer_value);
186 :     $decoded_answer_value = $answer_value;
187 :     } else {
188 :     $decoded_answer_value = decode_base64($answer_value);
189 :     if ( $decoded_answer_value =~/<XML|<?xml/i) { # great, we've decoded the answer to obtain an xml string
190 :     $base_64_encoded_answer_value = $answer_value;
191 :     } else { #WTF?? apparently we don't have XML tags
192 :     $answer_value = "<xml>$answer_value</xml>";
193 :     $base_64_encoded_answer_value = encode_base64($answer_value);
194 :     $decoded_answer_value = $answer_value;
195 :     }
196 : gage 6297 }
197 : gage 5677 $base_64_encoded_answer_value =~ s/\r|\n//g; # get rid of line returns
198 : gage 6297
199 :     ##########################
200 :     # Construct answer blank for storing state -- in both regular (answer blank hidden)
201 :     # and debug (answer blank displayed) modes.
202 :     ##########################
203 :    
204 :     ##########################
205 :     # debug version of the applet state answerBox and controls (all displayed)
206 :     # stored in
207 :     # $debug_input_element
208 :     ##########################
209 :    
210 : gage 6368 # my $debug_input_element = qq!\n<textarea rows="4" cols="80"
211 :     # name = "$appletStateName" id = "$appletStateName">$decoded_answer_value</textarea><br/>!;
212 :     # conversion to base64 is now being done in the setState module
213 :     # when submitting we want everything to be in the base64 mode for safety
214 : gage 5618 my $debug_input_element = qq!\n<textarea rows="4" cols="80"
215 : gage 6372 name = "$appletStateName" id = "$appletStateName">$answer_value</textarea><br/>!;
216 : gage 6368
217 : gage 6178 if ($getState=~/\S/) { # if getStateAlias is not an empty string
218 :     $debug_input_element .= qq!
219 : gage 5623 <input type="button" value="$getState"
220 : gage 6297 onClick=" debugText='';
221 :     ww_applet_list['$appletName'].getState() ;
222 : gage 6079 if (debugText) {alert(debugText)};"
223 : gage 6316 />!;
224 : gage 6178 }
225 :     if ($setState=~/\S/) { # if setStateAlias is not an empty string
226 :     $debug_input_element .= qq!
227 : gage 5623 <input type="button" value="$setState"
228 : gage 5993 onClick="debugText='';
229 :     ww_applet_list['$appletName'].setState();
230 : gage 6079 if (debugText) {alert(debugText)};"
231 : gage 6316 />!;
232 : gage 6178 }
233 :     if ($getConfig=~/\S/) { # if getConfigAlias is not an empty string
234 :     $debug_input_element .= qq!
235 : gage 6019 <input type="button" value="$getConfig"
236 :     onClick="debugText='';
237 : gage 6079 ww_applet_list['$appletName'].getConfig();
238 :     if (debugText) {alert(debugText)};"
239 : gage 6316 />!;
240 : gage 6178 }
241 :     if ($setConfig=~/\S/) { # if setConfigAlias is not an empty string
242 :     $debug_input_element .= qq!
243 : gage 6019 <input type="button" value="$setConfig"
244 :     onClick="debugText='';
245 : gage 6026 ww_applet_list['$appletName'].setConfig();
246 : gage 6079 if (debugText) {alert(debugText)};"
247 : gage 6316 />!;
248 : gage 6178 }
249 : gage 6297
250 :     ##########################
251 :     # Construct answerblank for storing state
252 :     # using either the debug version (defined above) or the non-debug version
253 :     # where the state variable is hidden and the definition is very simple
254 :     # stored in
255 :     # $state_input_element
256 :     ##########################
257 : gage 6019
258 : gage 6026 my $state_input_element = ($debugMode) ? $debug_input_element :
259 : gage 6210 qq!\n<input type="hidden" name = "$appletStateName" id = "$appletStateName" value ="$base_64_encoded_answer_value">!;
260 : gage 6297
261 :     ##########################
262 :     # Construct the reset button string (this is blank if the button is not to be displayed
263 :     # $reset_button_str
264 :     ##########################
265 :    
266 : gage 5618 my $reset_button_str = ($reset_button) ?
267 : gage 6297 qq!<input type='submit' name='previewAnswers' id ='previewAnswers' value='return this question to its initial state'
268 : gage 6368 onClick="setHTMLAppletStateToRestart('$appletName')"><br/>!
269 : gage 6030 : '' ;
270 : gage 6297
271 :     ##########################
272 :     # Combine the state_input_button and the reset button into one string
273 :     # $state_storage_html_code
274 :     ##########################
275 :    
276 :    
277 : gage 6210 $state_storage_html_code = qq!<input type="hidden" name="previous_$appletStateName" id = "previous_$appletStateName" value = "$base_64_encoded_answer_value">!
278 : gage 6030 . $state_input_element. $reset_button_str
279 : gage 5993 ;
280 : gage 6297 ##########################
281 :     # Construct the answerBox (if it is requested). This is a default input box for interacting
282 :     # with the applet. It is separate from maintaining state but it often contains similar data.
283 :     # Additional answer boxes or buttons can be defined but they must be explicitly connected to
284 :     # the applet with additional javaScript commands.
285 :     # Result: $answerBox_code
286 :     ##########################
287 :    
288 : gage 6030 my $answerBox_code ='';
289 :     if ($includeAnswerBox) {
290 :     if ($debugMode) {
291 :    
292 :     $answerBox_code = $main::BR . main::NAMED_ANS_RULE('answerBox', 50 );
293 :     $answerBox_code .= qq!
294 :     <br/><input type="button" value="get Answer from applet" onClick="eval(ww_applet_list['$appletName'].submitActionScript )"/>
295 :     <br/>
296 :     !;
297 :     } else {
298 :     $answerBox_code = main::NAMED_HIDDEN_ANS_RULE('answerBox', 50 );
299 :     }
300 :     }
301 : gage 6297
302 :     ##########################
303 : gage 5618 # insert header material
304 : gage 6297 ##########################
305 : gage 5582 main::HEADER_TEXT($self->insertHeader());
306 : gage 6026 # update the debug mode for this applet.
307 : gage 6316 main::HEADER_TEXT(qq!<script language="javascript"> ww_applet_list["$appletName"].debugMode = $debugMode;\n</script>!);
308 : gage 6297
309 :     ##########################
310 :     # Return HTML or TeX strings to be included in the body of the page
311 :     ##########################
312 :    
313 : gage 6010 return main::MODES(TeX=>' {\bf applet } ', HTML=>$self->insertObject.$main::BR.$state_storage_html_code.$answerBox_code);
314 : gage 5582 }
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 : gage 5618 # Add additional javaScript functions to header section of HTML to
358 : gage 5593 # communicate with the "ExternalInterface" applet.
359 : gage 5582 ###################################
360 :    
361 :     $applet->header(<<'END_HEADER');
362 : gage 6316 <script language="javascript" src="https://devel.webwork.rochester.edu:8002/webwork2_files/js/BrowserSniffer.js">
363 : gage 5582 </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 : gage 5618 getQE("playbackStatus").value = sMessage;
376 : gage 5582 }
377 :    
378 :     function newColor() {
379 : gage 5618
380 :     getApplet("ExternalInterface").updateColor(Math.round(Math.random() * 0xFFFFFF));
381 : gage 5582 }
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 : gage 5618 \{ $applet->insertAll() \}
405 : gage 5582 $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 : gage 6372 =cut

aubreyja at gmail dot com
ViewVC Help
Powered by ViewVC 1.0.9