[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 5971 - (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 5971 # $CVSHeader: pg/macros/AppletObjects.pl,v 1.11 2008/05/22 19:17:10 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 5667 sub _AppletObjects_init {
43 : gage 5618
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 : gage 5660 //////////////////////////////////////////////////////////
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 : gage 5618
67 : gage 5660 //////////////////////////////////////////////////////////
68 :     // DEBUGGING tools
69 :     //////////////////////////////////////////////////////////
70 : gage 5662 var debug;
71 : gage 5660 var debugText = "";
72 : gage 5662 function set_debug(num) { // setting debug for any applet sets it for all of them
73 :     if (num) {
74 :     debug =1;
75 :     }
76 :     }
77 : gage 5660 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 : gage 5618 function submitAction() {
88 : gage 5677
89 :     if (debug) {
90 :     debugText = " Begin looping through applet_submitAction_list\n";
91 :     }
92 : gage 5667 for (var applet in applet_submitAction_list) {
93 : gage 5677
94 : gage 5667 applet_submitAction_list[applet]();
95 :     }
96 : gage 5677 if (debug) {
97 :     alert(debugText); debugText="";
98 :     };
99 : gage 5618 }
100 :     function initializeAction() {
101 : gage 5660 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 : gage 5618
107 :     }
108 : gage 5660
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 : gage 5618
115 : gage 5660 // 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 : gage 5667 getApplet(appletName).debug(1); // turn the applet's debug functions on.
133 : gage 5660 }
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 : gage 5618
158 : gage 5660
159 : gage 5618 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 : gage 5660 return( obj );
165 : gage 5618 } else {
166 : gage 5660 // alert ("can't find applet " + appletName);
167 : gage 5618 }
168 :     }
169 : gage 5660
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 : gage 5618
218 :     </script>
219 :    
220 :     END_HEADER_TEXT
221 :    
222 : gage 5667 };
223 : gage 5618
224 : gage 5582 =head3
225 :     FlashApplet
226 :    
227 :     Useage: $applet = FlashApplet();
228 :    
229 :     =cut
230 :    
231 :     sub FlashApplet {
232 : gage 5597 return new FlashApplet(@_);
233 : gage 5582
234 :     }
235 :    
236 : gage 5618 sub JavaApplet {
237 :     return new JavaApplet(@_);
238 : gage 5582
239 : gage 5618 }
240 :    
241 :     package Applet;
242 :    
243 :    
244 :    
245 : gage 5582 =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 : gage 5618 =head3 insertAll
255 : gage 5582
256 : gage 5618 Useage: TEXT( $applet->insertAll() );
257 :     \{ $applet->insertAll() \} (used within BEGIN_TEXT/END_TEXT blocks)
258 : gage 5582
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 : gage 5618 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 : gage 5582
268 : gage 5618 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 : gage 5582 =cut
273 :    
274 : gage 5618 sub insertAll { ## inserts both header text and object text
275 : gage 5582 my $self = shift;
276 : gage 5618 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 : gage 5667 my $base_64_encoded_answer_value = ($answer_value =~/<XML|<?xml/i)? encode_base64($answer_value) : $answer_value;
301 : gage 5677 $base_64_encoded_answer_value =~ s/\r|\n//g; # get rid of line returns
302 : gage 5667 my $decoded_answer_value = ($answer_value =~/<XML|<?xml/i) ? $answer_value : decode_base64($answer_value);
303 : gage 5618 my $debug_input_element = qq!\n<textarea rows="4" cols="80"
304 :     name = "$appletStateName">$decoded_answer_value</textarea><br/>
305 : gage 5623 <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 : gage 5618 !;
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 : gage 5660 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 : gage 5618 : ''
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 : gage 5582 main::HEADER_TEXT($self->insertHeader());
330 : gage 5618 return main::MODES(TeX=>' {\bf applet } ', HTML=>$self->insertObject.$main::BR.$state_storage_html_code);
331 : gage 5582 }
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 : gage 5618 # Add additional javaScript functions to header section of HTML to
375 : gage 5593 # communicate with the "ExternalInterface" applet.
376 : gage 5582 ###################################
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 : gage 5618 getQE("playbackStatus").value = sMessage;
393 : gage 5582 }
394 :    
395 :     function newColor() {
396 : gage 5618
397 :     getApplet("ExternalInterface").updateColor(Math.round(Math.random() * 0xFFFFFF));
398 : gage 5582 }
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 : gage 5618 \{ $applet->insertAll() \}
422 : gage 5582 $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