[system] / trunk / pg / lib / Applet.pm Repository:
ViewVC logotype

Diff of /trunk/pg/lib/Applet.pm

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

Revision 5994 Revision 6026
1################################################################################ 1################################################################################
2# WeBWorK Online Homework Delivery System 2# WeBWorK Online Homework Delivery System
3# Copyright 2000-2007 The WeBWorK Project, http://openwebwork.sf.net/ 3# Copyright 2000-2007 The WeBWorK Project, http://openwebwork.sf.net/
4# $CVSHeader: pg/lib/Applet.pm,v 1.14 2009/01/28 17:07:08 gage Exp $ 4# $CVSHeader: pg/lib/Applet.pm,v 1.20 2009/03/10 20:58:46 gage Exp $
5# 5#
6# This program is free software; you can redistribute it and/or modify it under 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 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 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. 9# version, or (b) the "Artistic License" which comes with this package.
21=head1 SYNPOSIS 21=head1 SYNPOSIS
22 22
23 ################################### 23 ###################################
24 # Create link to applet 24 # Create link to applet
25 ################################### 25 ###################################
26 my $appletName = "LineThruPointsWW"; 26 $appletName = "PointGraph";
27 $applet = new FlashApplet( 27$applet = FlashApplet(
28 # can be replaced by $applet =FlashApplet() when using AppletObjects.pl
29 codebase => findAppletCodebase("$appletName.swf"), 28 codebase => findAppletCodebase("$appletName.swf"),
30 appletName => $appletName, 29 appletName => $appletName,
31 appletId => $appletName, 30 appletId => $appletName,
32 submitActionAlias => 'checkAnswer', 31 setStateAlias => 'setXML',
33 ); 32 getStateAlias => 'getXML',
34 33 setConfigAlias => 'config',
34 answerBoxAlias => 'receivedField',
35);
36
35 ################################### 37###################################
36 # Configure applet 38# Configure applet
37 ################################### 39###################################
38 40
39 #xml data to set up the problem-rac 41#data to set up the equation
40 $applet->config(qq{<XML> 42$applet->config(qq{<XML expr='(x - $a)^3 + $b/$a * x' />});
41 <point xval='$xval_1' yval='$yval_1' /> 43# initial points
42 <point xval='$xval_2' yval='$yval_2' /> 44$applet->state(qq{<XML>
43 </XML>}); 45</XML>});
44
45
46 ################################### 46###################################
47 # insert applet header material 47#insert applet into body
48 ################################### 48###################################
49 HEADER_TEXT($applet->insertHeader ); 49
50
51 ###################################
52 # Text section
53 #
54
55 ###################################
56 #insert applet into body
57 ###################################
58 TEXT( MODES(TeX=>'object code', HTML=>$applet->insertObject)); 50TEXT( MODES(TeX=>'object code', HTML=>$applet->insertAll(
51 debug=>0,
52 reset_button=>1,
53 )));
59 54
60 55
61=head1 DESCRIPTION 56=head1 DESCRIPTION
62 57
63This file provides an object to store in one place 58This file provides an object to store in one place
108 103
109 getApplet(appletName) -- finds the applet path in the DOM 104 getApplet(appletName) -- finds the applet path in the DOM
110 105
111 submitAction() -- calls the submit action of the applets 106 submitAction() -- calls the submit action of the applets
112 107
113 initializeWWquestion() -- calls the initialize action of the applets 108 initializeWWquestion() -- calls the initialize action of the applets
114 109
115 getQE(name) -- gets an HTML element of the question by name 110 getQE(name) -- gets an HTML element of the question by name
116 or by id. Be sure to keep all names and ids 111 or by id. Be sure to keep all names and ids
117 unique within a given PG question. 112 unique within a given PG question.
118 113
124 Usage: Place this at the END of the question, just before END_DOCUMENT(): 119 Usage: Place this at the END of the question, just before END_DOCUMENT():
125 120
126 TEXT(qq!<script> listQuestionElements() </script>!); 121 TEXT(qq!<script> listQuestionElements() </script>!);
127 ENDDOCUMENT(); 122 ENDDOCUMENT();
128 to obtain a list of all of the HTML elements in the question 123 to obtain a list of all of the HTML elements in the question
129 124
125 ----------------------------------------------------------------------------
126
127
130 List of accessor methods made available by the FlashApplet class: 128 List of accessor methods made available by the FlashApplet class:
131 Usage: $current_value = $applet->method(new_value or empty) 129 Usage: $current_value = $applet->method(new_value or empty)
132 These can also be set when creating the class -- for exampe: 130 These can also be set when creating the class -- for exampe:
133 $applet = new FlashApplet( 131 $applet = new FlashApplet(
134 # can be replaced by $applet =FlashApplet() when using AppletObjects.pl 132 # can be replaced by $applet =FlashApplet() when using AppletObjects.pl
158 config configuration are those customizable attributes of the applet which don't 156 config configuration are those customizable attributes of the applet which don't
159 change as it is used. When stored in hidden answer fields 157 change as it is used. When stored in hidden answer fields
160 it is usually stored in base64 encoded format. 158 it is usually stored in base64 encoded format.
161 base64_config base64 encode version of the contents of config 159 base64_config base64 encode version of the contents of config
162 160
163 configAlias (default: config ) names the applet command called with the contents of $self->config 161 configAlias (default: setConfig ) names the applet command called with the contents of $self->config
164 to configure the applet. The parameters are passed to the applet in plain text using <xml> 162 to configure the applet. The parameters are passed to the applet in plain text using <xml>
165 The outer tags must be <xml> ..... </xml> 163 The outer tags must be <xml> ..... </xml>
164 setConfigAlias (default: setConfig) -- a synonym for configAlias
165 getConfigAlias (default: getConfig) -- retrieves the configuration from the applet. This is used
166 mainly for debugging. In principal the configuration remains the same for a given instance
167 of the applet -- i.e. for the homework question for a single student. The state however
168 will change depending on the interactions between the student and the applet.
166 state state consists of those customizable attributes of the applet which change 169 initialState the state consists of those customizable attributes of the applet which change
167 as the applet is used. It is stored by the calling .pg question so that 170 as the applet is used by the student. It is stored by the calling .pg question so that
168 when revisiting the question the applet
169 will be restored to the same state it was left in when the question was last 171 when revisiting the question the applet will be restored to the same state it was left in when the question was last
170 viewed. 172 viewed.
171 173
172 getStateAlias (default: getState) alias for command called to read the current state of the applet. 174 getStateAlias (default: getState) alias for command called to read the current state of the applet.
173 The state is passed in plain text xml format with outer tags: <xml>....</xml> 175 The state is passed in plain text xml format with outer tags: <xml>....</xml>
174 setStateAlias (default: setState) alias for the command called to reset the state of the applet. 176 setStateAlias (default: setState) alias for the command called to reset the state of the applet.
177 base64_state returns the base64 encoded version of the state stored in the applet object. 179 base64_state returns the base64 encoded version of the state stored in the applet object.
178 180
179 initializeActionAlias -- (default: initializeAction) the name of the javaScript subroutine called to initialize the applet (some overlap with config/ and setState 181 initializeActionAlias -- (default: initializeAction) the name of the javaScript subroutine called to initialize the applet (some overlap with config/ and setState
180 submitActionAlias -- (default: submitAction)the name of the javaScript subroutine called when the submit button of the 182 submitActionAlias -- (default: submitAction)the name of the javaScript subroutine called when the submit button of the
181 .pg question is pressed. 183 .pg question is pressed.
182 answerBox -- name of answer box to return answer to: default defaultAnswerBox 184 answerBoxAlias -- name of answer box to return answer to: default defaultAnswerBox
183 getAnswer -- (formerly sendData) get student answer from applet and place in answerBox 185 getAnswer -- (formerly sendData) get student answer from applet and place in answerBox
184 returnFieldName -- (deprecated) synonmym for answerBox 186 returnFieldName -- (deprecated) synonmym for answerBoxAlias
185 187
186 188
187=cut 189=cut
188 190
191=head4 More details
189 192
193There are three different "images" of the applet. The first is the java or flash applet itself. The object that actually does the work.
194The second is a perl image of the applet -- henceforth the perlApplet -- which is configured in the .pg file and allows a WeBWorK question
195to communicate with the applet. The third image is a javaScript image of the applet -- henceforth the jsApplet which is a mirror of the perlApplet
196but is available to the javaScript code setup and executed in the virtual HTML page defined by the .pg file of the WeBWorK question. One can think of
197the jsApplet as a runtime version of the perlApplet since it can be accessed and modified after the virtual HTML page has been created by
198the PG rendering process.
190 199
200The perlApplet is initialized by $newApplet = new flashApplet( appletName=>'myApplet',..... ); The jsApplet is automatically defined in
201ww_applet_list["myApplet"] by copying the instance variables of $newApplet to a corresponding javaScript object. So $newApplet->{appletName}
202corresponds to ww_applet_list["myApplet"].appletName. (This paragraph is not yet fully implemented :-().
203
204Currently all messages read by the applet are xml text. If some of the code needs to be printed in the HTML header than it is converted
205to a base64 constant and then converted back to text form when it is read by a javaScript subroutine.
206
207The perlApplet has methods that help place the jsApplet code on the HTML page and create the link to the applet itself.
208In particular instance variables such as "setStateAlias", "getStateAlias" connect the WW default of "setState" to subroutine
209name chosen by the applet designer. The aim is to make it easier to connect to applets previously designed to work
210with javaScript in an HTML page or other systems.
211
212
213The jsApplet acts as an intermediary for commands directed at the applet.
214It is not necessary for the minimal operations of
215configuring the applet and maintaining
216state from one viewing of the WW question to address the applet directly.
217The methods such as "setState", "getState", "setConfig" which are part of the jsApplet
218take care of the book keeping details.
219It is also possible to make direct calls to the applet from handcrafted javaScript subroutines,
220but it may be convenient to store these as additional methods in the
221jsApplet.
222
223=cut
224
225=head4 Detecting that the applet is ready
226
227Timing issues are among the pitfalls awaiting when using flash or java applets in WW questions. It is important that the WW question
228does not issue any commands to the applet until the applet is fully loaded, including the uploading of any additional configuration
229information from XML files. This can be tricky since the timing issues usually don't arise when initiating the applet from an HTML page.
230
231The WW API performs the following actions to determine if the applet is loaded:
232
233 check the ww_applet_list[appletName].isReady flag (1== applet is ready)
234 -- this caches the readiness information so that it doesn't
235 have to be repeated within a given viewing of a WW question
236 If this is 1 then the applet is ready.
237 determine whether the applet's isActive subroutine is defined AND returns 1 when called.
238 -- if the return value is 1 the applet is ready, if it is zero or no response then the applet is NOT ready
239 -- If the applet has an isActive() subroutine -- there is no alias for this --
240 then it must return 1 as soon as the applet is ready. Otherwise
241 the applet will timeout.
242 determine whether the applet's setConfig subroutine is defined.
243 -- applet.{setConfigAlias}.
244 determine whether the applet's setState subroutine is defined.
245 determine whether the jsApplets ww_applet_list[appletName].reportsLoaded flag is set to 1
246 -- this can be set by the applet if it calls the javaScript function
247 "applet_loaded(appletName, loaded_status). The loaded_status is 1 or 0
248
249 Logic for determining applet status: if any one of the above checks succeeds (or returns 1) then the applet is
250 consdered to be ready UNLESS the isActive() exists and the call returns a 0 or no response. In this case
251 the applet is assumed to be loading additional data and is not yet ready.
252
253 For this reason if the isActive subroutine
254 is defined in the applet it must return a 1 once the applet is prepared to accept additional commands.
255 (Since there are some extent flashApplets with non-functioning isActive() subroutines a temporary workaround
256 assuems that after C<maxInitializationAttempts> -- 5 by default -- the applet is in fact ready but the
257 isActive() subroutine is non functioning. This can give rise to false "readiness" signals if the applet
258 takes a long time to load auxiliary files.)
259
260The applet itself can take measures to insure that the setConfig subroutine is prepared to respond immediately once the applet is loaded.
261It can include timers that delay execution of the configuring actions until all of the auxiliary files needed by the applet are loaded.
262
263
264=cut
265
266
267=head4 Initialization sequence
268
269When the WW question is loaded the C<initializeWWquestion> javaScript subroutine calls each of the applets used in the question asking them
270to initialize themselves.
271
272The applets initialization method is as follows:
273
274 -- wait until the applet is loaded and the applet has loaded all of its auxiliary files.
275 -- set the debugMode in the applet
276 -- call the setConfig method in the javaScript applet -- (configuration parameters are "permanent" for the life of the applet
277 -- call the setInitialization method in the javaScript applet -- this often calls the setState method in the applet
278
279=cut
280
281=head Methods defined for the javaScript applet ww_applet_list[appletName]
282
283This is not a comprehensive list
284
285 setConfig -- transmits the information for configuring the applet
286
287 getConfig -- retrieves the configuration information -- this is used mainly for debugging and may not be defined in most applets
288
289
290 setState -- sets the current state (1) from the appletName_state HTML element if this contains an <xml>...</xml> string
291 -- if the value contains <xml>restart_applet</xml> then set the current state to ww_applet_list[appletName].initialState
292 -- if the value is a blank string set the current state to ww_applet_list[appletName].initialState
293
294
295 getState -- retrieves the current state and stores in the appletName_state HTML element.
296
297
298
299
300
301
302
303=head Submit sequence
304
305When the WW question submit button is pressed the form containing the WW question calles the javaScript "submitAction()" which then asks
306each of the applets on the page to perform its submit action which consists of
307
308 -- if the applet is to be reinitialized (appletName_state contains <xml>restart_applet</xml>) then
309 the HTML elements appletName_state and previous_appletName_state are set to <xml>restart_applet</xml>
310 to be interpreted by the next setState command
311 -- Otherwise getState() from the applet and save it to the HTML input element appletName_state
312 -- Perform the javaScript commands in .submitActionScript (default: '' )
313 a typical submitActionScript looks like getQE(this.answerBox).value = getApplet(appletName).getAnswer() )
314
315=head4 Requirements for applets
316
317The following methods are desirable in an applet that preserves state in a WW question. None of them are required.
318
319 setState(str) (default: setXML)
320 -- set the current state of the applet from an xml string
321 -- should be able to accept an empty string or a string of
322 the form <XML>.....</XML> without creating errors
323 -- can be designed to receive other forms of input if it is
324 coordinated with the WW question.
325 getState() (default: getXML)
326 -- return the current state of the applet in an xml string.
327 -- an empty string or a string of the form <XML>.....</XML>
328 are the standard responses.
329 -- can be designed to return other strings if it is
330 coordinated with the WW question.
331 setConfig(str) (default: setConfig)
332 -- If the applet allows configuration this configures the applet
333 from an xml string
334 -- should be able to accept an empty string or a string of the
335 form <XML>.....</XML> without creating errors
336 -- can be designed to receive other forms of input if it is
337 coordinated with the WW question.
338 getConfig (default: getConfig)
339 -- This returns a string defining the configuration of the
340 applet in an xml string
341 -- an empty string or a string of the form <XML>.....</XML>
342 are the standard responses.
343 -- can be designed to return other strings if it is
344 coordinated with the WW question.
345 -- this method is used for debugging to ensure that
346 the configuration was set as expected.
347 getAnswer (default: getAnswer)
348 -- Returns a string (usually NOT xml) which is the
349 response that the student is effectvely submitting to answer
350 the WW question.
351
352
353=cut
191 354
192sub new { 355sub new {
193 my $class = shift; 356 my $class = shift;
194 my $self = { 357 my $self = {
195 appletName =>'', 358 appletName =>'',
197 codebase=>'', 360 codebase=>'',
198# appletId =>'', #always use identical applet Id's and applet Names 361# appletId =>'', #always use identical applet Id's and applet Names
199 params =>undef, 362 params =>undef,
200 width => 550, 363 width => 550,
201 height => 400, 364 height => 400,
365 bgcolor => "#869ca7",
202 base64_state => undef, # this is an state to use for initializing the first occurence of the question. 366 base64_state => undef, # this is a state to use for initializing the first occurence of the question.
203 base64_config => undef, # this is the initial (and final?) configuration 367 base64_config => undef, # this is the initial (and final?) configuration
368# configuration => '', # configuration defining the applet
369 initialState => '', # initial state. (I'm considering storing everything as ascii and converting on the fly to base64 when needed.)
204 getStateAlias => 'getXML', 370 getStateAlias => 'getXML',
205 setStateAlias => 'setXML', 371 setStateAlias => 'setXML',
372 configAlias => '', # deprecated
206 configAlias => 'config', 373 getConfigAlias => 'getConfig',
374 setConfigAlias => 'setConfig',
207 initializeActionAlias => 'setXML', 375 initializeActionAlias => 'setXML',
376 maxInitializationAttempts => 5, # number of attempts to initialize applet
208 submitActionAlias => 'getXML', 377 submitActionAlias => 'getXML',
209 submitActionScript => '', # script executed on submitting the WW question 378 submitActionScript => '', # script executed on submitting the WW question
210 answerBox => 'answerBox', 379 answerBoxAlias => 'answerBox',
380 answerBox => '', # deprecated
381 returnFieldName => '', # deprecated
211 headerText => DEFAULT_HEADER_TEXT(), 382 headerText => DEFAULT_HEADER_TEXT(),
212 objectText => '', 383 objectText => '',
213 debug => 0, 384 debugMode => 0,
214 @_, 385 @_,
215 }; 386 };
216 bless $self, $class; 387 bless $self, $class;
217 $self->state('<xml></xml>'); 388 $self->initialState('<xml></xml>');
389 if ($self->{returnFieldName} or $self->{answerBox} ) { # backward compatibility
390 warn "use answerBoxAlias instead of returnFieldName or answerBox";
391 $self->{answerBox}='';
392 $self->{returnFieldName}='';
393 }
394 if ($self->{configAlias}) { # backward compatibility
395 warn "use setConfigAlias instead of configAlias";
396 $self->{configAlias}='';
397 }
218 $self->config('<xml></xml>'); 398 $self->config('<xml></xml>');
219 return $self; 399 return $self;
220} 400}
221 401
222sub header { 402sub header {
276 $self->{setStateAlias} = shift ||$self->{setStateAlias}; # replace the current contents if non-empty 456 $self->{setStateAlias} = shift ||$self->{setStateAlias}; # replace the current contents if non-empty
277 $self->{setStateAlias}; 457 $self->{setStateAlias};
278} 458}
279sub configAlias { 459sub configAlias {
280 my $self = shift; 460 my $self = shift;
281 $self->{configAlias} = shift ||$self->{configAlias}; # replace the current contents if non-empty 461 $self->{setConfigAlias} = shift ||$self->{setConfigAlias}; # replace the current contents if non-empty
282 $self->{configAlias}; 462 $self->{setConfigAlias};
283} 463}
284sub returnFieldName { 464sub setConfigAlias {
465 my $self = shift;
466 $self->{setConfigAlias} = shift ||$self->{setConfigAlias}; # replace the current contents if non-empty
467 $self->{setConfigAlias};
468}
469sub getConfigAlias {
470 my $self = shift;
471 $self->{getConfigAlias} = shift ||$self->{getConfigAlias}; # replace the current contents if non-empty
472 $self->{getConfigAlias};
473}
474
475sub answerBoxName {
285 my $self = shift; 476 my $self = shift;
286 $self->{answerBox} = shift ||$self->{answerBox}; # replace the current contents if non-empty 477 $self->{answerBox} = shift ||$self->{answerBox}; # replace the current contents if non-empty
287 $self->{answerBox}; 478 $self->{answerBox};
288} 479}
289sub answerBox {
290 my $self = shift;
291 $self->{answerBox} = shift ||$self->{answerBox}; # replace the current contents if non-empty
292 $self->{answerBox};
293}
294sub codebase { 480sub codebase {
295 my $self = shift; 481 my $self = shift;
296 $self->{codebase} = shift ||$self->{codebase}; # replace the current codebase if non-empty 482 $self->{codebase} = shift ||$self->{codebase}; # replace the current codebase if non-empty
297 $self->{codebase}; 483 $self->{codebase};
298} 484}
309sub width { 495sub width {
310 my $self = shift; 496 my $self = shift;
311 $self->{width} = shift ||$self->{width}; # replace the current width if non-empty 497 $self->{width} = shift ||$self->{width}; # replace the current width if non-empty
312 $self->{width}; 498 $self->{width};
313} 499}
500sub bgcolor {
501 my $self = shift;
502 $self->{bgcolor} = shift ||$self->{bgcolor}; # replace the current background color if non-empty
503 $self->{bgcolor};
504}
314sub archive { 505sub archive {
315 my $self = shift; 506 my $self = shift;
316 $self->{archive} = shift ||$self->{archive}; # replace the current archive if non-empty 507 $self->{archive} = shift ||$self->{archive}; # replace the current archive if non-empty
317 $self->{archive}; 508 $self->{archive};
318} 509}
319sub appletName { 510sub appletName {
320 my $self = shift; 511 my $self = shift;
321 $self->{appletName} = shift ||$self->{appletName}; # replace the current appletName if non-empty 512 $self->{appletName} = shift ||$self->{appletName}; # replace the current appletName if non-empty
322 $self->{appletName}; 513 $self->{appletName};
323} 514}
324sub debug { 515sub debugMode {
325 my $self = shift; 516 my $self = shift;
326 my $new_flag = shift; 517 my $new_flag = shift;
327 $self->{debug} = $new_flag if defined($new_flag); 518 $self->{debugMode} = $new_flag if defined($new_flag);
328 $self->{debug}; 519 $self->{debugMode};
329} 520}
330sub appletId { 521sub appletId {
331 appletName(@_); 522 appletName(@_);
332} 523}
524sub maxInitializationAttempts {
525 my $self = shift;
526 $self->{maxInitializationAttempts} = shift || $self->{maxInitializationAttempts};
527 $self->{maxInitializationAttempts};
528}
529sub initialState {
530 my $self = shift;
531 my $str = shift;
532 $self->{initialState} = $str ||$self->{initialState}; # replace the current string if non-empty
533 $self->{initialState};
534}
535
536sub config {
537 my $self = shift;
538 my $str = shift;
539 $self->{base64_config} = encode_base64($str) || $self->{base64_config}; # replace the current string if non-empty
540 $self->{base64_config} =~ s/\n//g;
541 decode_base64($self->{base64_config});
542}
543#######################
544# soon to be deprecated?
545#######################
333sub state { 546sub state {
334 my $self = shift; 547 my $self = shift;
335 my $str = shift; 548 my $str = shift;
336 $self->{base64_state} = encode_base64($str) ||$self->{base64_state}; # replace the current string if non-empty 549 $self->{base64_state} = encode_base64($str) ||$self->{base64_state}; # replace the current string if non-empty
337 $self->{base64_state} =~ s/\n//g; 550 $self->{base64_state} =~ s/\n//g;
338 decode_base64($self->{base64_state}); 551 decode_base64($self->{base64_state});
339} 552}
340
341sub base64_state{ 553sub base64_state{
342 my $self = shift; 554 my $self = shift;
343 $self->{base64_state} = shift ||$self->{base64_state}; # replace the current string if non-empty 555 $self->{base64_state} = shift ||$self->{base64_state}; # replace the current string if non-empty
344 $self->{base64_state}; 556 $self->{base64_state};
345} 557}
346sub config { 558
347 my $self = shift;
348 my $str = shift;
349 $self->{base64_config} = encode_base64($str) || $self->{base64_config}; # replace the current string if non-empty
350 $self->{base64_config} =~ s/\n//g;
351 decode_base64($self->{base64_config});
352}
353sub base64_config { 559sub base64_config {
354 my $self = shift; 560 my $self = shift;
355 $self->{base64_config} = shift ||$self->{base64_config}; # replace the current string if non-empty 561 $self->{base64_config} = shift ||$self->{base64_config}; # replace the current string if non-empty
356 $self->{base64_config} =$self->{base64_config}; 562 $self->{base64_config} =$self->{base64_config};
357 $self->{base64_config}; 563 $self->{base64_config};
358} 564}
565
566sub returnFieldName {
567 my $self = shift;
568 warn "use answerBoxName instead of returnFieldName";
569}
570sub answerBox {
571 my $self = shift;
572 warn "use answerBoxAlias instead of AnswerBox";
573}
574#########################
359#FIXME 575#FIXME
360# need to be able to adjust header material 576# need to be able to adjust header material
361 577
362sub insertHeader { 578sub insertHeader {
363 my $self = shift; 579 my $self = shift;
580
364 my $codebase = $self->codebase; 581 my $codebase = $self->codebase;
365 my $appletId = $self->appletId; 582 my $appletId = $self->appletId;
366 my $appletName = $self->appletName; 583 my $appletName = $self->appletName;
367 my $base64_initialState = $self->base64_state; 584 my $base64_initialState = $self->base64_state;
368 my $initializeAction = $self->initializeActionAlias; 585 my $initializeActionAlias = $self->initializeActionAlias;
369 my $submitAction = $self->submitActionAlias; 586 my $submitActionAlias = $self->submitActionAlias;
370 my $submitActionScript = $self->submitActionScript; 587 my $submitActionScript = $self->submitActionScript;
371 my $setState = $self->setStateAlias; 588 my $setStateAlias = $self->setStateAlias;
372 my $getState = $self->getStateAlias; 589 my $getStateAlias = $self->getStateAlias;
590
373 my $config = $self->configAlias; 591 my $setConfigAlias = $self->setConfigAlias;
592 my $getConfigAlias = $self->getConfigAlias;
593 my $maxInitializationAttempts = $self->maxInitializationAttempts;
374 my $base64_config = $self->base64_config; 594 my $base64_config = $self->base64_config;
375 my $debugMode = ($self->debug) ? "1": "0"; 595 my $debugMode = ($self->debugMode) ? "1": "0";
376 my $returnFieldName = $self->{returnFieldName};
377 my $answerBox = $self->{answerBox}; 596 my $answerBoxAlias = $self->{answerBoxAlias};
378 my $headerText = $self->header(); 597 my $headerText = $self->header();
598
599
600 $submitActionScript =~ s/"/\\"/g; # escape quotes for ActionScript
601 # other variables should not have quotes.
602
603 $submitActionScript =~ s/\n/ /g; # replace returns with spaces -- returns in the wrong spot can cause trouble with javaScript
604 $submitActionScript =~ s/\r/ /g; # replace returns with spaces -- returns can cause trouble
605 my $base64_submitActionScript = encode_base64($submitActionScript);
606 $base64_submitActionScript =~s/\n//g;
379 607
380 $headerText =~ s/(\$\w+)/$1/gee; # interpolate variables p17 of Cookbook 608 $headerText =~ s/(\$\w+)/$1/gee; # interpolate variables p17 of Cookbook
381 609
382 return $headerText; 610 return $headerText;
383 611
391 my $appletId = $self->{appletName}; 619 my $appletId = $self->{appletName};
392 my $appletName = $self->{appletName}; 620 my $appletName = $self->{appletName};
393 my $archive = $self->{archive}; 621 my $archive = $self->{archive};
394 my $width = $self->{width}; 622 my $width = $self->{width};
395 my $height = $self->{height}; 623 my $height = $self->{height};
624 my $applet_bgcolor = $self->{bgcolor};
396 my $javaParameters = ''; 625 my $javaParameters = '';
397 my $flashParameters = ''; 626 my $flashParameters = '';
398 my %param_hash = %{$self->params()}; 627 my %param_hash = %{$self->params()};
399 foreach my $key (keys %param_hash) { 628 foreach my $key (keys %param_hash) {
400 $javaParameters .= qq!<param name ="$key" value = "$param_hash{$key}">\n!; 629 $javaParameters .= qq!<param name ="$key" value = "$param_hash{$key}">\n!;
422######################################################## 651########################################################
423 652
424use constant DEFAULT_HEADER_TEXT =><<'END_HEADER_SCRIPT'; 653use constant DEFAULT_HEADER_TEXT =><<'END_HEADER_SCRIPT';
425 <script src="/webwork2_files/js/Base64.js" language="javascript"> 654 <script src="/webwork2_files/js/Base64.js" language="javascript">
426 </script> 655 </script>
427 <script src="/webwork2_files/js/ww_applet_support.js"> 656 <script src="/webwork2_files/js/ww_applet_support.js" language="javascript">
428 //upload functions stored in /opt/webwork/webwork2/htdocs/js ... 657 //upload functions stored in /opt/webwork/webwork2/htdocs/js ...
658
429 </script> 659 </script>
430 <script language="JavaScript"> 660 <script language="JavaScript">
431 661
432 // set debug mode for this applet 662
433 set_debug($debugMode);
434 663
435 ////////////////////////////////////////////////////////// 664 //////////////////////////////////////////////////////////
436 //TEST code 665 //TEST code
437 // 666 //
438 // 667 //
440 669
441 ww_applet_list["$appletName"] = new ww_applet("$appletName"); 670 ww_applet_list["$appletName"] = new ww_applet("$appletName");
442 671
443 672
444 ww_applet_list["$appletName"].code = "$code"; 673 ww_applet_list["$appletName"].code = "$code";
445 ww_applet_list["$appletName"].codebase = "$codebase"; 674 ww_applet_list["$appletName"].codebase = "$codebase";
446 ww_applet_list["$appletName"].appletID = "$appletID"; 675 ww_applet_list["$appletName"].appletID = "$appletID";
447 ww_applet_list["$appletName"].base64_state = "$base64_initializationState"; 676 ww_applet_list["$appletName"].base64_state = "$base64_initializationState";
677 ww_applet_list["$appletName"].initialState = Base64.decode("$base64_intialState");
448 ww_applet_list["$appletName"].base64_config = "$base64_config"; 678 ww_applet_list["$appletName"].base64_config = "$base64_config";
449 ww_applet_list["$appletName"].getStateAlias = "$getState"; 679 ww_applet_list["$appletName"].getStateAlias = "$getStateAlias";
450 ww_applet_list["$appletName"].setStateAlias = "$setState"; 680 ww_applet_list["$appletName"].setStateAlias = "$setStateAlias";
451 ww_applet_list["$appletName"].configAlias = "$config"; 681 ww_applet_list["$appletName"].setConfigAlias = "$setConfigAlias";
682 ww_applet_list["$appletName"].getConfigAlias = "$getConfigAlias";
452 ww_applet_list["$appletName"].initializeActionAlias = "$initializeAction"; 683 ww_applet_list["$appletName"].initializeActionAlias = "$initializeActionAlias";
453 ww_applet_list["$appletName"].submitActionAlias = "$submitAction"; 684 ww_applet_list["$appletName"].submitActionAlias = "$submitActionAlias";
454 ww_applet_list["$appletName"].submitActionScript = "$submitActionScript"; 685 ww_applet_list["$appletName"].submitActionScript = Base64.decode("$submitActionScript_base64");
455 ww_applet_list["$appletName"].answerBox = "$answerBox"; 686 ww_applet_list["$appletName"].answerBoxAlias = "$answerBoxAlias";
687 ww_applet_list["$appletName"].maxInitializationAttempts = $maxInitializationAttempts;
456 ww_applet_list["$appletName"].debug = "$debugMode"; 688 ww_applet_list["$appletName"].debugMode = "$debugMode";
457 689
458
459 //////////////////////////////////////////////////////////
460 //CONFIGURATIONS
461 //
462 // configurations are "permanent"
463 //////////////////////////////////////////////////////////
464
465// applet_config_list["$appletName"] = function() {
466// debug_add("applet_config_list:\n attempt to configure $appletName . $config ( $base64_config ) if config function is defined: "
467// );
468// try {
469// if (( typeof(getApplet("$appletName").$config) == "function" ) ) {
470// debug_add("CONFIGURE $appletName");
471// getApplet("$appletName").$config(Base64.decode("$base64_config"));
472// }
473// } catch(e) {
474// alert("Error executing configuration command $config for $appletName: " + e );
475// }
476// }
477// ////////////////////////////////////////////////////////////
478// //
479// //STATE:
480// // state can vary as the applet is manipulated -- it is reset from the questions _state values
481// //
482// //////////////////////////////////////////////////////////
483//
484// applet_setState_list["$appletName"] = function(state) {
485// debug_add("Begin setState for applet $appletName");
486// debug_add("Obtain state from $appletName"+"_state");
487// state = state || getQE("$appletName"+"_state").value;
488// if ( base64Q(state) ) {
489// state=Base64.decode(state);
490// }
491// if (state.match(/<xml/i) || state.match(/<?xml/i) ) { // if state starts with <?xml
492//
493// debug_add("applet_setState_list: \n set (decoded) state for $appletName to " +
494// state +"\nfunction type is " +typeof(getApplet("$appletName").$setState)
495// );
496// try {
497// if (( typeof(getApplet("$appletName").$setState) =="function" ) ) {
498// debug_add("setState for $appletName");
499// getApplet("$appletName").$setState( state );
500// }
501// } catch(e) {
502// alert("Error in setting state of $appletName using command $setState : " + e );
503// }
504// } else if (debug) {
505// alert("new state was empty string or did not begin with <xml-- state was not reset");
506// }
507// };
508// applet_getState_list["$appletName"] = function () {
509// debug_add("get current state for applet $appletName and store it in $appletName"+"_state");
510// var applet = getApplet("$appletName");
511// try {
512// if (( typeof(applet.$getState) == "function" ) ) { // there may be no state function
513// state = applet.$getState(); // get state in xml format
514// debug_add("state has type " + typeof(state));
515// state = String(state); // geogebra returned an object type instead of a string type
516// debug_add("state converted to type " + typeof(state));
517// }
518//
519// if (!debug) {
520// state = Base64.encode(state);
521// }; // replace state by encoded version unless in debug mode
522//
523// debug_add("state is "+state); // this should still be in plain text
524// getQE("$appletName"+"_state").value = state; //place state in input item (debug: textarea, otherwise: hidden)
525// } catch (e) {
526// alert("Error in getting state for $appletName " + e );
527// }
528// };
529//
530// ////////////////////////////////////////////////////////////
531// //
532// //INITIALIZE
533// //
534// ////////////////////////////////////////////////////////////
535//
536//
537// applet_checkLoaded_list["$appletName"] = function() { // this function returns 0 unless:
538// // applet has already been flagged as ready in applet_isReady_list
539// // applet.config is defined (or alias for .config)
540// // applet.setState is defined
541// // applet.isActive is defined
542// // applet reported that it is loaded by calling loadQ()
543// var ready = 0;
544// var applet = getApplet("$appletName");
545// if (!debug && applet_isReady_list["$appletName"]) {return(1)}; // memorize readiness in non-debug mode
546// if ( typeof(applet.$config) == "function") {
547// debug_add( "applet.config is " + typeof(applet.$config) );
548// ready = 1;
549// }
550// if( typeof(applet.$getState) == "function") {
551// debug_add( "applet.getState is " + typeof(applet.$getState) );
552// ready =1;
553// }
554// if (typeof(applet.isActive) == "function" && applet.isActive ) {
555// debug_add( "applet.isActive is " + typeof(applet.isActive) );
556// ready =1;
557// }
558// if (typeof(applet_reportsLoaded_list["$appletName"]) !="undefined" && applet_reportsLoaded_list["$appletName"] != 0 ) {
559// debug_add( "applet reports that it is loaded " + applet_reportsLoaded_list["$appletName"] );
560// ready =1;
561// }
562// applet_isReady_list["$appletName"]= ready;
563// return(ready);
564// }
565//
566// applet_initializeAction_list["$appletName"] = function (state) {
567// applet_setState_list["$appletName"](state);
568// };
569//
570// applet_submitAction_list["$appletName"] = function () {
571// if (! applet_isReady_list["$appletName"] ) {
572// alert("$appletName is not ready");
573// }
574// applet_getState_list["$appletName"]();
575// $submitActionScript
576// //getQE("$answerBox").value = getApplet("$appletName").getAnswer(); //FIXME -- not needed in general?
577// };
578 </script> 690 </script>
579 691
580END_HEADER_SCRIPT 692END_HEADER_SCRIPT
581 693
582package FlashApplet; 694package FlashApplet;
604 <object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" 716 <object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
605 id="$appletName" width="500" height="375" 717 id="$appletName" width="500" height="375"
606 codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab"> 718 codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab">
607 <param name="movie" value="$codebase/$appletName.swf" /> 719 <param name="movie" value="$codebase/$appletName.swf" />
608 <param name="quality" value="high" /> 720 <param name="quality" value="high" />
609 <param name="bgcolor" value="#869ca7" /> 721 <param name="bgcolor" value="$applet_bgcolor" />
610 <param name="allowScriptAccess" value="sameDomain" /> 722 <param name="allowScriptAccess" value="sameDomain" />
611 <embed src="$codebase/$appletName.swf" quality="high" bgcolor="#869ca7" 723 <embed src="$codebase/$appletName.swf" quality="high" bgcolor="$applet_bgcolor"
612 width="$width" height="$height" name="$appletName" align="middle" id="$appletName" 724 width="$width" height="$height" name="$appletName" align="middle" id="$appletName"
613 play="true" loop="false" quality="high" allowScriptAccess="sameDomain" 725 play="true" loop="false" quality="high" allowScriptAccess="sameDomain"
614 type="application/x-shockwave-flash" 726 type="application/x-shockwave-flash"
615 pluginspage="http://www.macromedia.com/go/getflashplayer"> 727 pluginspage="http://www.macromedia.com/go/getflashplayer">
616 </embed> 728 </embed>
626 <object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" 738 <object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
627 id="$appletName" width="500" height="375" 739 id="$appletName" width="500" height="375"
628 codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab"> 740 codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab">
629 <param name="movie" value="$codebase/$appletName.swf" /> 741 <param name="movie" value="$codebase/$appletName.swf" />
630 <param name="quality" value="high" /> 742 <param name="quality" value="high" />
631 <param name="bgcolor" value="#869ca7" /> 743 <param name="bgcolor" value="$applet_bgcolor" />
632 <param name="allowScriptAccess" value="sameDomain" /> 744 <param name="allowScriptAccess" value="sameDomain" />
633 <param name="FlashVars" value="$flashParameters"/> 745 <param name="FlashVars" value="$flashParameters"/>
634 <embed src="$codebase/$appletName.swf" quality="high" bgcolor="#869ca7" 746 <embed src="$codebase/$appletName.swf" quality="high" bgcolor="$applet_bgcolor"
635 width="$width" height="$height" name="$appletName" align="middle" id="$appletName" 747 width="$width" height="$height" name="$appletName" align="middle" id="$appletName"
636 play="true" loop="false" quality="high" allowScriptAccess="sameDomain" 748 play="true" loop="false" quality="high" allowScriptAccess="sameDomain"
637 type="application/x-shockwave-flash" 749 type="application/x-shockwave-flash"
638 pluginspage="http://www.macromedia.com/go/getflashplayer" 750 pluginspage="http://www.macromedia.com/go/getflashplayer"
639 FlashVars="$flashParameters"> 751 FlashVars="$flashParameters">
696 archive = "$archive" 808 archive = "$archive"
697 name = "$appletName" 809 name = "$appletName"
698 id = "$appletName" 810 id = "$appletName"
699 width = "$width" 811 width = "$width"
700 height = "$height" 812 height = "$height"
813 bgcolor = "$applet_bgcolor"
701 MAYSCRIPT 814 MAYSCRIPT
702 > 815 >
703 $javaParameters 816 $javaParameters
704 817
705 Sorry, the Applet could not be started. Please make sure that 818 Sorry, the Applet could not be started. Please make sure that

Legend:
Removed from v.5994  
changed lines
  Added in v.6026

aubreyja at gmail dot com
ViewVC Help
Powered by ViewVC 1.0.9