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

Diff of /branches/gage_dev/pg/lib/Applet.pm

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

trunk/pg/lib/Applet.pm Revision 5622 branches/gage_dev/pg/lib/Applet.pm Revision 6324
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.5 2008/03/16 14:39:39 gage Exp $ 4# $CVSHeader$
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 => 'answerBox',
35 submitActionScript => qq{ getQE('answerBox').value = getApplet("$appletName").getAnswer() },
36);
37
35 ################################### 38###################################
36 # Configure applet 39# Configure applet
37 ################################### 40###################################
38 41
39 #xml data to set up the problem-rac 42#data to set up the equation
40 $applet->state(qq{<XML> 43$applet->configuration(qq{<XML expr='(x - $a)^3 + $b/$a * x' />});
41 <point xval='$xval_1' yval='$yval_1' /> 44# initial points
42 <point xval='$xval_2' yval='$yval_2' /> 45$applet->intialState(qq{<XML> </XML>});
43 </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 includeAnswerBox => 1
52 debug=>0,
53 reinitialize_button=>1,
54 )));
59 55
60 56
61=head1 DESCRIPTION 57=head1 DESCRIPTION
62 58
63This file provides an object to store in one place 59This file provides an object to store in one place
90 86
91 87
92 88
93package Applet; 89package Applet;
94 90
95 91use URI::Escape;
96 92
97 93
98 94
99use MIME::Base64 qw( encode_base64 decode_base64); 95use MIME::Base64 qw( encode_base64 decode_base64);
100 96
101 97
102=head2 Default javaScript functions placed in header 98=head2 Default javaScript functions placed in header
99
100=pod
103 101
104These functions are automatically defined for use for 102These functions are automatically defined for use for
105any javaScript placed in the text of a PG question. 103any javaScript placed in the text of a PG question.
106 104
107 getApplet(appletName) -- finds the applet path in the DOM 105 getApplet(appletName) -- finds the applet path in the DOM
108 106
109 submitAction() -- calls the submit action of the applets 107 submitAction() -- calls the submit action of the applets
110
111 108
112 initializeAction() -- calls the initialize action of the applets 109 initializeWWquestion() -- calls the initialize action of the applets
113 110
114 getQE(name) -- gets an HTML element of the question by name 111 getQE(name) -- gets an HTML element of the question by name
115 or by id. Be sure to keep all names and ids 112 or by id. Be sure to keep all names and ids
116 unique within a given PG question. 113 unique within a given PG question.
117 114
118 getQuestionElement(name) -- long form of getQE(name) 115 getQuestionElement(name) -- long form of getQE(name)
119 116
120 listQuestionElements() -- for discovering the names of inputs in the 117 listQuestionElements() -- for discovering the names of inputs in the
121 PG question. An alert dialog will list all 118 PG question. An alert dialog will list all
122 of the elements. 119 of the elements.
120
123 Usage: Place this at the END of the question, 121 Usage: Place this at the END of the question, just before END_DOCUMENT():
124 just before END_DOCUMENT():
125 122
126 TEXT(qq!<script> listQuestionElements() </script>!); 123 TEXT(qq!<script> listQuestionElements() </script>!);
127 ENDDOCUMENT(); 124 ENDDOCUMENT();
125 to obtain a list of all of the HTML elements in the question
126
127 ----------------------------------------------------------------------------
128
129
130 List of accessor methods made available by the FlashApplet class:
131 Usage: $current_value = $applet->method(new_value or empty)
132 These can also be set when creating the class -- for exampe:
133 $applet = new FlashApplet(
134 # can be replaced by $applet =FlashApplet() when using AppletObjects.pl
135 codebase => findAppletCodebase("$appletName.swf"),
136 appletName => $appletName,
137 appletId => $appletName,
138 submitActionAlias => 'checkAnswer',
139 );
128 140
129 list of accessor methods format: current_value = $self->method(new_value or empty)
130 141
131 appletId for simplicity and reliability appletId and appletName are always the same 142 appletId for simplicity and reliability appletId and appletName are always the same
132 appletName 143 appletName
144 archive the name of the .jar file containing the applet code
145 code the name of the applet code in the .jar archive
146 codebase a prefix url used to find the archive and the applet itself
147
148 params an anonymous array containing name/value pairs
149 to configure the applet [name =>'value, ...]
150
151 width rectangle alloted in the html page for displaying the applet
152 height
153
154 bgcolor background color of the applet rectangle
133 155
134 archive the name of the .jar file containing the applet code
135 code the name of the applet code in the .jar archive
136 codebase a prefix url used to find the archive and the applet itself
137
138 height rectangle alloted in the html page for displaying the applet
139 width
140
141 params an anonymous array containing name/value pairs
142 to configure the applet [name =>'value, ...]
143
144 header stores the text to be added to the header section of the html page 156 header stores the text to be added to the header section of the html page
145 object stores the text which places the applet on the html page 157 object stores the text which places the applet on the html page
146 158
147 debug in debug mode several alerts mark progress through the procedure of calling the applet 159
148
149 config configuration are those customizable attributes of the applet which don't 160 configuration configuration contains those customizable attributes of the applet which don't
150 change as it is used. When stored in hidden answer fields 161 change as it is used. When stored in hidden answer fields
151 it is usually stored in base64 encoded format. 162 it is usually stored in base64 encoded format.
152 base64_config base64 encode version of the contents of config 163 initialState the state consists of those customizable attributes of the applet which change
153 164 as the applet is used by the student. It is stored by the calling .pg question so that
165 when revisiting the question the applet will be restored to the same state it was
166 left in when the question was last viewed.
167
168 getStateAlias (default: getState) alias for command called to read the current state of the applet.
169 The state is passed in plain text xml format with outer tags: <xml>....</xml>
170 setStateAlias (default: setState) alias for the command called to reset the state of the applet.
171 The state is passed in plain text in xml format with outer tags: <xml>....</xml>
172
173 configAlias (deprecated) -- a synonym for configAlias
174
175 getConfigAlias (default: getConfig) -- retrieves the configuration from the applet. This is used
176 mainly for debugging. In principal the configuration remains the same for a given instance
177 of the applet -- i.e. for the homework question for a single student. The state however
178 will change depending on the interactions between the student and the applet.
154 configAlias (default: config ) names the applet command called with the contents of $self->config 179 setConfigAlias (default: setConfig ) names the applet command called with the contents of $self->config
155 to configure the applet. The parameters are passed to the applet in plain text using <xml> 180 to configure the applet. The parameters are passed to the applet in plain text using <xml>
156 The outer tags must be <xml> ..... </xml> 181 The outer tags must be <xml> ..... </xml>
157 state state consists of those customizable attributes of the applet which change
158 as the applet is used. It is stored by the calling .pg question so that
159 when revisiting the question the applet
160 will be restored to the same state it was left in when the question was last
161 viewed.
162
163 getStateAlias (default: getState) alias for command called to read the current state of the applet.
164 The state is passed in plain text xml format with outer tags: <xml>....</xml>
165 setStateAlias (default: setState) alias for the command called to reset the state of the applet.
166 The state is passed in plain text in xml format with outer tags: <xml>....</xml>
167 182
168 base64_state returns the base64 encoded version of the state stored in the applet object. 183
169 184 initializeActionAlias -- (default: initializeAction) the name of the javaScript subroutine called
170 initializeActionAlias -- (default: initializeAction) the name of the javaScript subroutine called to initialize the applet (some overlap with config/ and setState 185 to initialize the applet (some overlap with config/ and setState
186 maxInitializationAttempts -- (default: 5) number attempts to test applet to see if it is installed.
187 If isActive() exists then the WW question waits until the return value is 1 before
188 calling the applet's confguration commands.
189 Because some applets have isActive return 0 even when they are ready,
190 if isActive() exists but does not return 1 then the applet's configuration commands
191 are called after maxInitializationAttempts number of times. If none of the configuration commands
192 of the applet can be detected then the WW question gives up after maxInitializationAttempts.
193
171 submitActionAlias -- (default: submitAction)the name of the javaScript subroutine called when the submit button of the 194 submitActionAlias -- (default: getXML) applet subroutine called when the submit button of the
172 .pg question is pressed. 195 .pg question is pressed.
196 submitActionScript -- (default: qq{ getQE('answerBox').value = getApplet("$appletName").getAnswer() },
197
198 answerBoxAlias -- name of answer box to return answer to: default defaultAnswerBox
199 returnFieldName -- (deprecated) synonmym for answerBoxAlias
200
201
202 debugMode (default: 0) for debugMode==1 the answerBox and the box preserving the applet state
203 between questions are made visible along with some buttons for manually getting the state of
204 the applet and setting the state of the applet.
205
206 for debugMode==2, in addition to the answerBox and stateBox there are several alerts
207 which mark progress through the procedures of calling the applet. Useful for troubleshooting
208 where in the chain of command a communication failure occurs
173 209
174 returnFieldName 210
175 211 Methods:
176 212
213 insertHeader -- inserts text in header section of HTML page
214 insertObject -- inserts <object></object> or <applet></applet> tag in body of the HTML page
215 insertAll -- (defined in AppletObjects.pl) installs applet by inserting both header text and the object text
216 Usage: $applet->insertAll(
217 includeAnswerBox => 0,
218 debugMode => 0,
219 reinitialize_button =>0,
220 );
177 221
178
179 222
180=cut 223=cut
181 224
225=head4 More details
182 226
227There are three different "images" of the applet. The first is the java or flash applet itself. The object that actually does the work.
228The second is a perl image of the applet -- henceforth the perlApplet -- which is configured in the .pg file and allows a WeBWorK question
229to communicate with the applet. The third image is a javaScript image of the applet -- henceforth the jsApplet which is a mirror of the perlApplet
230but 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
231the jsApplet as a runtime version of the perlApplet since it can be accessed and modified after the virtual HTML page has been created by
232the PG rendering process.
233
234The perlApplet is initialized by $newApplet = new flashApplet( appletName=>'myApplet',..... ); The jsApplet is automatically defined in
235ww_applet_list["myApplet"] by copying the instance variables of $newApplet to a corresponding javaScript object. So $newApplet->{appletName}
236corresponds to ww_applet_list["myApplet"].appletName. (This paragraph is not yet fully implemented :-().
237
238Currently 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
239to a base64 constant and then converted back to text form when it is read by a javaScript subroutine.
240
241The perlApplet has methods that help place the jsApplet code on the HTML page and create the link to the applet itself.
242In particular instance variables such as "setStateAlias", "getStateAlias" connect the WW default of "setState" to subroutine
243name chosen by the applet designer. The aim is to make it easier to connect to applets previously designed to work
244with javaScript in an HTML page or other systems.
245
246
247The jsApplet acts as an intermediary for commands directed at the applet.
248It is not necessary for the minimal operations of
249configuring the applet and maintaining
250state from one viewing of the WW question to address the applet directly.
251The methods such as "setState", "getState", "setConfig" which are part of the jsApplet
252take care of the book keeping details.
253It is also possible to make direct calls to the applet from handcrafted javaScript subroutines,
254but it may be convenient to store these as additional methods in the
255jsApplet.
256
257=cut
258
259=head4 Detecting that the applet is ready
260
261Timing issues are among the pitfalls awaiting when using flash or java applets in WW questions. It is important that the WW question
262does not issue any commands to the applet until the applet is fully loaded, including the uploading of any additional configuration
263information from XML files. This can be tricky since the timing issues usually don't arise when initiating the applet from an HTML page.
264
265The WW API performs the following actions to determine if the applet is loaded:
266
267 check the ww_applet_list[appletName].isReady flag (1== applet is ready)
268 -- this caches the readiness information so that it doesn't
269 have to be repeated within a given viewing of a WW question
270 If this is 1 then the applet is ready.
271 determine whether the applet's isActive subroutine is defined AND returns 1 when called.
272 -- if the return value is 1 the applet is ready, if it is zero or no response then the applet is NOT ready
273 -- If the applet has an isActive() subroutine -- there is no alias for this --
274 then it must return 1 as soon as the applet is ready. Otherwise
275 the applet will timeout.
276 determine whether the applet's setConfig subroutine is defined.
277 -- applet.{setConfigAlias}.
278 determine whether the applet's setState subroutine is defined.
279 determine whether the jsApplets ww_applet_list[appletName].reportsLoaded flag is set to 1
280 -- this can be set by the applet if it calls the javaScript function
281 "applet_loaded(appletName, loaded_status). The loaded_status is 1 or 0
282
283 Logic for determining applet status: if any one of the above checks succeeds (or returns 1) then the applet is
284 consdered to be ready UNLESS the isActive() exists and the call returns a 0 or no response. In this case
285 the applet is assumed to be loading additional data and is not yet ready.
286
287 For this reason if the isActive subroutine
288 is defined in the applet it must return a 1 once the applet is prepared to accept additional commands.
289 (Since there are some extent flashApplets with non-functioning isActive() subroutines a temporary workaround
290 assuems that after C<maxInitializationAttempts> -- 5 by default -- the applet is in fact ready but the
291 isActive() subroutine is non functioning. This can give rise to false "readiness" signals if the applet
292 takes a long time to load auxiliary files.)
293
294The applet itself can take measures to insure that the setConfig subroutine is prepared to respond immediately once the applet is loaded.
295It can include timers that delay execution of the configuring actions until all of the auxiliary files needed by the applet are loaded.
296
297
298=cut
299
300
301
302
303=head4 Instance variables in the javaScript applet ww_applet_list[appletName]
304
305 Most of the instance variables in the perl version of the applet are transferred to the javaScript applet
306
307=cut
308
309
310=head4 Methods defined for the javaScript applet ww_applet_list[appletName]
311
312This is not a comprehensive list
313
314 setConfig -- transmits the information for configuring the applet
315
316 getConfig -- retrieves the configuration information -- this is used mainly for debugging and may not be defined in most applets
317
318
319 setState -- sets the current state (1) from the appletName_state HTML element if this contains an <xml>...</xml> string
320 -- if the value contains <xml>restart_applet</xml> then set the current state to ww_applet_list[appletName].initialState
321 -- if the value is a blank string set the current state to ww_applet_list[appletName].initialState
322
323
324 getState -- retrieves the current state and stores in the appletName_state HTML element.
325
326
327=cut
328
329=head4 Requirements for applets
330
331The following methods are desirable in an applet that preserves state in a WW question. None of them are required.
332
333 setState(str) (default: setXML)
334 -- set the current state of the applet from an xml string
335 -- should be able to accept an empty string or a string of
336 the form <XML>.....</XML> without creating errors
337 -- can be designed to receive other forms of input if it is
338 coordinated with the WW question.
339 getState() (default: getXML)
340 -- return the current state of the 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 setConfig(str) (default: setConfig)
346 -- If the applet allows configuration this configures the applet
347 from an xml string
348 -- should be able to accept an empty string or a string of the
349 form <XML>.....</XML> without creating errors
350 -- can be designed to receive other forms of input if it is
351 coordinated with the WW question.
352 getConfig (default: getConfig)
353 -- This returns a string defining the configuration of the
354 applet in an xml string
355 -- an empty string or a string of the form <XML>.....</XML>
356 are the standard responses.
357 -- can be designed to return other strings if it is
358 coordinated with the WW question.
359 -- this method is used for debugging to ensure that
360 the configuration was set as expected.
361 getAnswer (default: getAnswer)
362 -- Returns a string (usually NOT xml) which is the
363 response that the student is effectvely submitting to answer
364 the WW question.
365
366
367=cut
368
369=head4 Initialization sequence
370
371When the WW question is loaded the C<initializeWWquestion> javaScript subroutine calls each of the applets used in the question asking them
372to initialize themselves.
373
374The applets initialization method is as follows:
375
376 -- wait until the applet is loaded and the applet has loaded all of its auxiliary files.
377 -- set the debugMode in the applet
378 -- call the setConfig method in the javaScript applet -- (configuration parameters are "permanent" for the life of the applet
379 -- call the setInitialization method in the javaScript applet -- this often calls the setState method in the applet
380
381=cut
382
383
384=head Submit sequence
385
386When the WW question submit button is pressed the form containing the WW question calles the javaScript "submitAction()" which then asks
387each of the applets on the page to perform its submit action which consists of
388
389 -- if the applet is to be reinitialized (appletName_state contains <xml>restart_applet</xml>) then
390 the HTML elements appletName_state and previous_appletName_state are set to <xml>restart_applet</xml>
391 to be interpreted by the next setState command
392 -- Otherwise getState() from the applet and save it to the HTML input element appletName_state
393 -- Perform the javaScript commands in .submitActionScript (default: '' )
394 a typical submitActionScript looks like getQE(this.answerBox).value = getApplet(appletName).getAnswer() )
395
396=cut
183 397
184 398
185sub new { 399sub new {
186 my $class = shift; 400 my $class = shift;
187 my $self = { 401 my $self = {
188 appletName =>'', 402 appletName => '',
189 code=>'',
190 codebase=>'',
191# appletId =>'', #always use identical applet Id's and applet Names 403 appletId => '', #always use identical applet Id's and applet Names
404 archive => '',
405 code => '',
406 codebase => '',
192 params =>undef, 407 params =>undef,
193 width => 550, 408 width => 550,
194 height => 400, 409 height => 400,
195 base64_state => '', 410 bgcolor => "#869ca7",
196 base64_config => '', 411 configuration => '', # configuration defining the applet
412 initialState => '', # initial state.
197 getStateAlias => 'getXML', 413 getStateAlias => 'getXML',
198 setStateAlias => 'setState', 414 setStateAlias => 'setXML',
415 configAlias => '', # deprecated
199 configAlias => 'config', 416 getConfigAlias => 'getConfig',
417 setConfigAlias => 'setConfig',
200 initializeActionAlias => 'setXML', 418 initializeActionAlias => 'setXML',
419 maxInitializationAttempts => 5, # number of attempts to initialize applet
201 submitActionAlias => 'getXML', 420 submitActionAlias => 'getXML',
202 returnFieldName => 'receivedField', 421 submitActionScript => '', # script executed on submitting the WW question
422 answerBoxAlias => 'answerBox',
423 answerBox => '', # deprecated
424 returnFieldName => '', # deprecated
203 headerText => DEFAULT_HEADER_TEXT(), 425 headerText => DEFAULT_HEADER_TEXT(),
204 objectText => '', 426 objectText => '',
205 debug => 0, 427 debugMode => 0,
206 @_, 428 @_,
207 }; 429 };
208 bless $self, $class; 430 bless $self, $class;
431 $self->initialState('<xml></xml>');
432 if ($self->{returnFieldName} or $self->{answerBox} ) { # backward compatibility
433 warn "use answerBoxAlias instead of returnFieldName or answerBox";
434 $self->{answerBox}='';
435 $self->{returnFieldName}='';
436 }
437 if ($self->{configAlias}) { # backward compatibility
438 warn "use setConfigAlias instead of configAlias";
439 $self->{configAlias}='';
440 }
441 $self->configuration('<xml></xml>');
209 return $self; 442 return $self;
210} 443}
211 444sub appletId {
212sub header { 445 appletName(@_);
446}
447sub appletName {
213 my $self = shift; 448 my $self = shift;
214 if ($_[0] eq "reset") { # $applet->header('reset'); erases default header text. 449 $self->{appletName} = shift ||$self->{appletName}; # replace the current appletName if non-empty
215 $self->{headerText}=''; 450 $self->{appletName};
216 } else { 451}
217 $self->{headerText} .= join("",@_); # $applet->header(new_text); concatenates new_text to existing header. 452sub archive {
218 } 453 my $self = shift;
454 $self->{archive} = shift ||$self->{archive}; # replace the current archive if non-empty
455 $self->{archive};
456}
457sub code {
458 my $self = shift;
459 $self->{code} = shift ||$self->{code}; # replace the current code if non-empty
219 $self->{headerText}; 460 $self->{code};
220} 461}
221sub object { 462sub codebase {
222 my $self = shift; 463 my $self = shift;
223 if ($_[0] eq "reset") { 464 $self->{codebase} = shift ||$self->{codebase}; # replace the current codebase if non-empty
224 $self->{objectText}=''; 465 $self->{codebase};
225 } else {
226 $self->{objectText} .= join("",@_);
227 }
228 $self->{objectText};
229} 466}
230sub params { 467sub params {
231 my $self = shift; 468 my $self = shift;
232 if (ref($_[0]) =~/HASH/) { 469 if (ref($_[0]) =~/HASH/) {
233 $self->{params} = shift; 470 $self->{params} = shift;
236 } else { 473 } else {
237 warn "You must enter a reference to a hash for the parameter list"; 474 warn "You must enter a reference to a hash for the parameter list";
238 } 475 }
239 $self->{params}; 476 $self->{params};
240} 477}
241 478
479sub width {
480 my $self = shift;
481 $self->{width} = shift ||$self->{width}; # replace the current width if non-empty
482 $self->{width};
483}
484sub height {
485 my $self = shift;
486 $self->{height} = shift ||$self->{height}; # replace the current height if non-empty
487 $self->{height};
488}
489sub bgcolor {
490 my $self = shift;
491 $self->{bgcolor} = shift ||$self->{bgcolor}; # replace the current background color if non-empty
492 $self->{bgcolor};
493}
494
495sub header {
496 my $self = shift;
497 if ($_[0] eq "reset") { # $applet->header('reset'); erases default header text.
498 $self->{headerText}='';
499 } else {
500 $self->{headerText} .= join("",@_); # $applet->header(new_text); concatenates new_text to existing header.
501 }
502 $self->{headerText};
503}
504sub object {
505 my $self = shift;
506 if ($_[0] eq "reset") {
507 $self->{objectText}='';
508 } else {
509 $self->{objectText} .= join("",@_);
510 }
511 $self->{objectText};
512}
513sub configuration {
514 my $self = shift;
515 my $str = shift;
516 $self->{configuration} = $str || $self->{configuration}; # replace the current string if non-empty
517 $self->{configuration} =~ s/\n//g;
518 $self->{configuration};
519}
520
521sub initialState {
522 my $self = shift;
523 my $str = shift;
524 $self->{initialState} = $str ||$self->{initialState}; # replace the current string if non-empty
525 $self->{initialState};
526}
527
528sub getStateAlias {
529 my $self = shift;
530 $self->{getStateAlias} = shift ||$self->{getStateAlias}; # replace the current contents if non-empty
531 $self->{getStateAlias};
532}
533
534sub setStateAlias {
535 my $self = shift;
536 $self->{setStateAlias} = shift ||$self->{setStateAlias}; # replace the current contents if non-empty
537 $self->{setStateAlias};
538}
539
540sub getConfigAlias {
541 my $self = shift;
542 $self->{getConfigAlias} = shift ||$self->{getConfigAlias}; # replace the current contents if non-empty
543 $self->{getConfigAlias};
544}
545sub setConfigAlias {
546 my $self = shift;
547 $self->{setConfigAlias} = shift ||$self->{setConfigAlias}; # replace the current contents if non-empty
548 $self->{setConfigAlias};
549}
550
242sub initializeActionAlias { 551sub initializeActionAlias {
243 my $self = shift; 552 my $self = shift;
244 $self->{initializeActionAlias} = shift ||$self->{initializeActionAlias}; # replace the current contents if non-empty 553 $self->{initializeActionAlias} = shift ||$self->{initializeActionAlias}; # replace the current contents if non-empty
245 $self->{initializeActionAlias}; 554 $self->{initializeActionAlias};
246} 555}
247 556sub maxInitializationAttempts {
557 my $self = shift;
558 $self->{maxInitializationAttempts} = shift || $self->{maxInitializationAttempts};
559 $self->{maxInitializationAttempts};
560}
248sub submitActionAlias { 561sub submitActionAlias {
249 my $self = shift; 562 my $self = shift;
250 $self->{submitActionAlias} = shift ||$self->{submitActionAlias}; # replace the current contents if non-empty 563 $self->{submitActionAlias} = shift ||$self->{submitActionAlias}; # replace the current contents if non-empty
251 $self->{submitActionAlias}; 564 $self->{submitActionAlias};
252} 565}
253sub getStateAlias { 566sub submitActionScript {
567 my $self = shift;
568 $self->{submitActionScript} = shift ||$self->{submitActionScript}; # replace the current contents if non-empty
569 $self->{submitActionScript};
570}
571
572sub answerBoxAlias {
573 my $self = shift;
574 $self->{answerBox} = shift ||$self->{answerBox}; # replace the current contents if non-empty
575 $self->{answerBox};
576}
577
578sub debugMode {
579 my $self = shift;
580 my $new_flag = shift;
581 $self->{debugMode} = $new_flag if defined($new_flag);
582 $self->{debugMode};
583}
584
585
586#######################
587# soon to be deprecated?
588#######################
589
590sub config {
591 my $self = shift;
254 my $self = shift; 592 my $str = shift;
255 $self->{getStateAlias} = shift ||$self->{getStateAlias}; # replace the current contents if non-empty 593 warn "use $self->configuration instead of $self->config. Internally this string is ascii, not base64 encoded", join(' ', caller());
256 $self->{getStateAlias}; 594# $self->{base64_config} = encode_base64($str) || $self->{base64_config}; # replace the current string if non-empty
595# $self->{base64_config} =~ s/\n//g;
596# decode_base64($self->{base64_config});
257} 597}
258 598sub state {
259sub setStateAlias { 599 my $self = shift;
260 my $self = shift; 600 my $str = shift;
261 $self->{setStateAlias} = shift ||$self->{setStateAlias}; # replace the current contents if non-empty 601 warn "use $self->initialState instead of $self->state. Internally this string is ascii, not base64 encoded", join(' ', caller());
262 $self->{setStateAlias}; 602# $self->{base64_state} = encode_base64($str) ||$self->{base64_state}; # replace the current string if non-empty
603# $self->{base64_state} =~ s/\n//g;
604# decode_base64($self->{base64_state});
605}
606sub base64_state{
607 my $self = shift;
608 warn "use $self->InitialState instead of $self->state. Internally this string is ascii, not base64 encoded", join(' ', caller());
609
610
611}
612
613sub base64_config {
614 my $self = shift;
615 warn "use $self->configuration instead of $self->config. Internally this string is ascii, not base64 encoded";
616}
617
618sub returnFieldName {
619 my $self = shift;
620 warn "use answerBoxName instead of returnFieldName";
621}
622sub answerBox {
623 my $self = shift;
624 warn "use answerBoxAlias instead of AnswerBox";
263} 625}
264sub configAlias { 626sub configAlias {
265 my $self = shift; 627 my $self = shift;
266 $self->{configAlias} = shift ||$self->{configAlias}; # replace the current contents if non-empty 628 warn "use setConfigAlias instead of configAlias";
267 $self->{configAlias};
268} 629}
269sub returnFieldName { 630#########################
270 my $self = shift;
271 $self->{returnFieldName} = shift ||$self->{returnFieldName}; # replace the current contents if non-empty
272 $self->{returnFieldName};
273}
274sub codebase {
275 my $self = shift;
276 $self->{codebase} = shift ||$self->{codebase}; # replace the current codebase if non-empty
277 $self->{codebase};
278}
279sub code {
280 my $self = shift;
281 $self->{code} = shift ||$self->{code}; # replace the current code if non-empty
282 $self->{code};
283}
284sub height {
285 my $self = shift;
286 $self->{height} = shift ||$self->{height}; # replace the current height if non-empty
287 $self->{height};
288}
289sub width {
290 my $self = shift;
291 $self->{width} = shift ||$self->{width}; # replace the current width if non-empty
292 $self->{width};
293}
294sub archive {
295 my $self = shift;
296 $self->{archive} = shift ||$self->{archive}; # replace the current archive if non-empty
297 $self->{archive};
298}
299sub appletName {
300 my $self = shift;
301 $self->{appletName} = shift ||$self->{appletName}; # replace the current appletName if non-empty
302 $self->{appletName};
303}
304sub debug {
305 my $self = shift;
306 my $new_flag = shift;
307 $self->{debug} = $new_flag if defined($new_flag);
308 $self->{debug};
309}
310sub appletId {
311 appletName(@_);
312}
313sub state {
314 my $self = shift;
315 my $str = shift;
316 $self->{base64_state} = encode_base64($str) ||$self->{base64_state}; # replace the current string if non-empty
317 $self->{base64_state} =~ s/\n//g;
318 decode_base64($self->{base64_state});
319}
320
321sub base64_state{
322 my $self = shift;
323 $self->{base64_state} = shift ||$self->{base64_state}; # replace the current string if non-empty
324 $self->{base64_state};
325}
326sub config {
327 my $self = shift;
328 my $str = shift;
329 $self->{base64_config} = encode_base64($str) || $self->{base64_config}; # replace the current string if non-empty
330 $self->{base64_config} =~ s/\n//g;
331 decode_base64($self->{base64_config});
332}
333sub base64_config {
334 my $self = shift;
335 $self->{base64_config} = shift ||$self->{base64_config}; # replace the current string if non-empty
336 $self->{base64_config} =$self->{base64_config};
337 $self->{base64_config};
338}
339#FIXME 631#FIXME
340# need to be able to adjust header material 632# need to be able to adjust header material
341 633
342sub insertHeader { 634sub insertHeader {
343 my $self = shift; 635 my $self = shift;
636
344 my $codebase = $self->codebase; 637 my $codebase = $self->codebase;
345 my $appletId = $self->appletId; 638 my $appletId = $self->appletId;
346 my $appletName = $self->appletName; 639 my $appletName = $self->appletName;
347 my $base64_initialState = $self->base64_state;
348 my $initializeAction = $self->initializeActionAlias; 640 my $initializeActionAlias = $self->initializeActionAlias;
349 my $submitAction = $self->submitActionAlias; 641 my $submitActionScript = $self->submitActionScript;
350 my $setState = $self->setStateAlias; 642 my $setStateAlias = $self->setStateAlias;
351 my $getState = $self->getStateAlias; 643 my $getStateAlias = $self->getStateAlias;
644
352 my $config = $self->configAlias; 645 my $setConfigAlias = $self->setConfigAlias;
353 my $base64_config = $self->base64_config; 646 my $getConfigAlias = $self->getConfigAlias;
647 my $maxInitializationAttempts = $self->maxInitializationAttempts;
354 my $debugMode = ($self->debug) ? "1": "0"; 648 my $debugMode = ($self->debugMode) ? "1": "0";
355 my $returnFieldName = $self->{returnFieldName}; 649 my $answerBoxAlias = $self->{answerBoxAlias};
356# my $encodeStateQ = ($self->debug)?'' : "state = Base64.encode(state);"; # in debug mode base64 encoding is not used.
357# my $decodeStateQ = "if (!state.match(/<XML>*/i) ) {state = Base64.decode(state)}"; # decode if <XML> is not present
358 my $headerText = $self->header(); 650 my $headerText = $self->header();
651
652
653 #$submitActionScript =~ s/"/\\"/g; # escape quotes for ActionScript
654 # other variables should not have quotes.
655
656 $submitActionScript =~ s/\n/ /g; # replace returns with spaces -- returns in the wrong spot can cause trouble with javaScript
657 $submitActionScript =~ s/\r/ /g; # replace returns with spaces -- returns can cause trouble
658 my $base64_submitActionScript = encode_base64($submitActionScript);
659 my $base64_configuration = encode_base64($self->configuration);
660 my $base64_initialState = encode_base64($self->initialState);
661
662 $base64_submitActionScript =~s/\n//g;
663 $base64_initialState =~s/\n//g; # base64 encoded xml
664 $base64_configuration =~s/\n//g; # base64 encoded xml
359 665
360 $headerText =~ s/(\$\w+)/$1/gee; # interpolate variables p17 of Cookbook 666 $headerText =~ s/(\$\w+)/$1/gee; # interpolate variables p17 of Cookbook
361 667
362 return $headerText; 668 return $headerText;
363 669
364 670
365} 671}
672
673
674########################################################
675# HEADER material for one flash or java applet
676########################################################
677
678use constant DEFAULT_HEADER_TEXT =><<'END_HEADER_SCRIPT';
679 <script src="/webwork2_files/js/Base64.js" language="javascript">
680 </script>
681 <script src="/webwork2_files/js/ww_applet_support.js" language="javascript">
682 //upload functions stored in /opt/webwork/webwork2/htdocs/js ...
683
684 </script>
685 <script language="JavaScript">
686
687 function getApplet(appletName) {
688 var isIE = navigator.appName.indexOf("Microsoft") != -1; // ie8 uses this for java and firefox uses it for flash.
689 var obj = (isIE) ? window[appletName] : window.document[appletName];
690 //return window.document[appletName];
691 if (!obj) { obj = document.getElementById(appletName) }
692 if (obj ) { //RECENT FIX to ==
693 return( obj );
694 } else {
695 alert ("can't find applet " + appletName);
696 }
697 }
698
699 //////////////////////////////////////////////////////////
700 //TEST code
701 //
702 //
703 //////////////////////////////////////////////////////////
704
705 ww_applet_list["$appletName"] = new ww_applet("$appletName");
706
707
708 ww_applet_list["$appletName"].code = "$code";
709 ww_applet_list["$appletName"].codebase = "$codebase";
710 ww_applet_list["$appletName"].appletID = "$appletID";
711 ww_applet_list["$appletName"].base64_state = "$base64_initializationState";
712 ww_applet_list["$appletName"].initialState = Base64.decode("$base64_initialState");
713 ww_applet_list["$appletName"].configuration = Base64.decode("$base64_configuration");;
714 ww_applet_list["$appletName"].getStateAlias = "$getStateAlias";
715 ww_applet_list["$appletName"].setStateAlias = "$setStateAlias";
716 ww_applet_list["$appletName"].setConfigAlias = "$setConfigAlias";
717 ww_applet_list["$appletName"].getConfigAlias = "$getConfigAlias";
718 ww_applet_list["$appletName"].initializeActionAlias = "$initializeActionAlias";
719 ww_applet_list["$appletName"].submitActionAlias = "$submitActionAlias";
720 ww_applet_list["$appletName"].submitActionScript = Base64.decode("$base64_submitActionScript");
721 ww_applet_list["$appletName"].answerBoxAlias = "$answerBoxAlias";
722 ww_applet_list["$appletName"].maxInitializationAttempts = $maxInitializationAttempts;
723 ww_applet_list["$appletName"].debugMode = "$debugMode";
724
725 </script>
726
727END_HEADER_SCRIPT
728
729
366 730
367sub insertObject { 731sub insertObject {
368 my $self = shift; 732 my $self = shift;
369 my $code = $self->{code}; 733 my $code = $self->{code};
370 my $codebase = $self->{codebase}; 734 my $codebase = $self->{codebase};
371 my $appletId = $self->{appletName}; 735 my $appletId = $self->{appletName};
372 my $appletName = $self->{appletName}; 736 my $appletName = $self->{appletName};
373 my $archive = $self->{archive}; 737 my $archive = $self->{archive};
374 my $width = $self->{width}; 738 my $width = $self->{width};
375 my $height = $self->{height}; 739 my $height = $self->{height};
740 my $applet_bgcolor = $self->{bgcolor};
376 my $parameters = ''; 741 my $javaParameters = '';
377 my $parameters = ''; 742 my $flashParameters = '';
378 my %param_hash = %{$self->params()}; 743 my %param_hash = %{$self->params()};
379 foreach my $key (keys %param_hash) { 744 foreach my $key (keys %param_hash) {
380 $parameters .= qq!<param name ="$key" value = "$param_hash{$key}">\n! 745 $javaParameters .= qq!<param name ="$key" value = "$param_hash{$key}">\n!;
746 $flashParameters .= uri_escape($key).'='.uri_escape($param_hash{$key}).'&';
381 } 747 }
748 $flashParameters =~ s/\&$//; # trim last &
382 749
750
383 $objectText = $self->{objectText}; 751 $objectText = $self->{objectText};
384 $objectText =~ s/(\$\w+)/$1/gee; 752 $objectText =~ s/(\$\w+)/$1/gee;
385 return $objectText; 753 return $objectText;
386} 754}
387sub initialize {
388 my $self = shift;
389 return q{
390 <script>
391 initializeAction();
392 // this should really be done in the <body> tag
393 </script>
394 };
395 755
396}
397 756
398 757###############################################################################################################
399use constant DEFAULT_HEADER_TEXT =><<'END_HEADER_SCRIPT'; 758#
400 759# FLASH APPLET PACKAGE
401 <script language="JavaScript"> 760#
402 var debug = $debugMode; 761###############################################################################################################
403 //
404 //CONFIGURATIONS
405 //
406 // configurations are "permanent"
407 applet_config_list["$appletName"] = function() {
408 if (debug) { alert("configure $appletName . $config ( $base64_config )");}
409 try {
410 if (debug || !( typeof(getApplet("$appletName").$config) == "undefined" ) ) {
411
412 getApplet("$appletName").$config(Base64.decode("$base64_config"));
413 }
414 } catch(e) {
415 alert("error executing configuration command $config for $appletName: " + e );
416 }
417 }
418 //
419 //STATE
420 //
421 // state can vary as the applet is manipulated.
422 applet_setState_list["$appletName"] = function(state) {
423 state = state || getQE("$appletName"+"_state").value
424 if (state.match("\S") ) { // if state is not all white space
425 if ( base64Q(state) ) {
426 state=Base64.decode(state);
427 }
428 if (debug) { alert("set state for $appletName to " + state);}
429 try {
430 if (debug || !( typeof(getApplet("$appletName").$setState) =="undefined" ) ) {
431 getApplet("$appletName").$setState( state );
432 }
433 } catch(e) {
434 alert("Error in setting state of $appletName using command $setState : " + e );
435 }
436 }
437 };
438 applet_getState_list["$appletName"] = function () {
439 if (debug) { alert("getState for applet $appletName");}
440 try {
441 var applet = getApplet("$appletName");
442 var state;
443 if (!( typeof(getApplet("$appletName").$getState) =="undefined" ) ) {
444 state = applet.$getState(); // get state in xml format
445 }
446 if (!debug) {state = Base64.encode(state) }; // replace state by encoded version
447 getQE("$appletName"+"_state").value = state; //place in state htmlItem (debug: textarea, otherwise hidden)
448 } catch (e) {
449 alert("Error in getting state for $appletName " + e );
450 }
451 };
452 //
453 //INITIALIZE
454 //
455 applet_initializeAction_list["$appletName"] = function () {
456 applet_setState_list["$appletName"]();
457 };
458
459 applet_submitAction_list["$appletName"] = function () {
460 applet_getState_list["$appletName"]();
461 getQE("$returnFieldName").value = getApplet("$appletName").sendData();
462 };
463 </script>
464
465END_HEADER_SCRIPT
466 762
467package FlashApplet; 763package FlashApplet;
468@ISA = qw(Applet); 764@ISA = qw(Applet);
469 765
470 766
767=head2 Insertion HTML code for FlashApplet
471 768
472=pod 769=pod
473 770
474The secret to making this applet work with IE in addition to normal browsers 771The secret to making this applet work with IE in addition to normal browsers
475is the addition of the C(<form></form>) construct just before the object. 772is the addition of the C(<form></form>) construct just before the object.
488 <object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" 785 <object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
489 id="$appletName" width="500" height="375" 786 id="$appletName" width="500" height="375"
490 codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab"> 787 codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab">
491 <param name="movie" value="$codebase/$appletName.swf" /> 788 <param name="movie" value="$codebase/$appletName.swf" />
492 <param name="quality" value="high" /> 789 <param name="quality" value="high" />
493 <param name="bgcolor" value="#869ca7" /> 790 <param name="bgcolor" value="$applet_bgcolor" />
494 <param name="allowScriptAccess" value="sameDomain" /> 791 <param name="allowScriptAccess" value="sameDomain" />
495 <embed src="$codebase/$appletName.swf" quality="high" bgcolor="#869ca7" 792 <embed src="$codebase/$appletName.swf" quality="high" bgcolor="$applet_bgcolor"
496 width="$width" height="$height" name="$appletName" align="middle" id="$appletName" 793 width="$width" height="$height" name="$appletName" align="middle" id="$appletName"
497 play="true" loop="false" quality="high" allowScriptAccess="sameDomain" 794 play="true" loop="false" quality="high" allowScriptAccess="sameDomain"
498 type="application/x-shockwave-flash" 795 type="application/x-shockwave-flash"
499 pluginspage="http://www.macromedia.com/go/getflashplayer"> 796 pluginspage="http://www.macromedia.com/go/getflashplayer">
500 </embed> 797 </embed>
504 801
505 802
506=cut 803=cut
507 804
508use constant DEFAULT_OBJECT_TEXT =><<'END_OBJECT_TEXT'; 805use constant DEFAULT_OBJECT_TEXT =><<'END_OBJECT_TEXT';
509 <form></form> 806<<<<<<< .working
807
510 <object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" 808 <object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
511 id="$appletName" width="500" height="375" 809 id="$appletName" width="500" height="375"
810=======
811
812 <object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
813 id="$appletName" width="500" height="375"
814>>>>>>> .merge-right.r6319
512 codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab"> 815 codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab">
513 <param name="movie" value="$codebase/$appletName.swf" /> 816 <param name="movie" value="$codebase/$appletName.swf" />
514 <param name="quality" value="high" /> 817 <param name="quality" value="high" />
515 <param name="bgcolor" value="#869ca7" /> 818 <param name="bgcolor" value="$applet_bgcolor" />
516 <param name="allowScriptAccess" value="sameDomain" /> 819 <param name="allowScriptAccess" value="sameDomain" />
820 <param name="FlashVars" value="$flashParameters"/>
517 <embed src="$codebase/$appletName.swf" quality="high" bgcolor="#869ca7" 821 <embed src="$codebase/$appletName.swf" quality="high" bgcolor="$applet_bgcolor"
518 width="$width" height="$height" name="$appletName" align="middle" id="$appletName" 822 width="$width" height="$height" name="$appletName" align="middle" id="$appletName"
519 play="true" loop="false" quality="high" allowScriptAccess="sameDomain" 823 play="true" loop="false" quality="high" allowScriptAccess="sameDomain"
520 type="application/x-shockwave-flash" 824 type="application/x-shockwave-flash"
521 pluginspage="http://www.macromedia.com/go/getflashplayer"> 825 pluginspage="http://www.macromedia.com/go/getflashplayer"
826 FlashVars="$flashParameters">
522 </embed> 827 </embed>
523 828
524 </object> 829 </object>
525END_OBJECT_TEXT 830END_OBJECT_TEXT
526 831
530 @_ 835 @_
531 ); 836 );
532 837
533} 838}
534 839
840###############################################################################################################
841#
842# JAVA APPLET PACKAGE
843#
844###############################################################################################################
535 845
536package JavaApplet; 846package JavaApplet;
537@ISA = qw(Applet); 847@ISA = qw(Applet);
538 848
539 849=head2 Insertion HTML code for JavaApplet
540 850
541=pod 851=pod
542 852
543The secret to making this applet work with IE in addition to normal browsers 853The secret to making this applet work with IE in addition to normal browsers
544is the addition of the C(<form></form>) construct just before the object. 854is the addition of the C(<form></form>) construct just before the object.
562 id = "$appletName" 872 id = "$appletName"
563 width = "$width" 873 width = "$width"
564 height = "$height" 874 height = "$height"
565 MAYSCRIPT 875 MAYSCRIPT
566 > 876 >
567 $parameters 877 $javaParameters
568 </applet> 878 </applet>
569 END_OBJECT_TEXT 879 END_OBJECT_TEXT
570 880
571=cut 881=cut
572 882
883
884=pod
885
573use constant DEFAULT_OBJECT_TEXT =><<'END_OBJECT_TEXT'; 886use constant DEFAULT_OBJECT_TEXT =><<'END_OBJECT_TEXT';
574 <form></form> 887
575 <applet 888 <applet
576 code = "$code" 889 code = "$code"
577 codebase = "$codebase" 890 codebase = "$codebase"
578 archive = "$archive" 891 archive = "$archive"
579 name = "$appletName" 892 name = "$appletName"
580 id = "$appletName" 893 id = "$appletName"
581 width = "$width" 894 width = "$width"
582 height = "$height" 895 height = "$height"
896 bgcolor = "$applet_bgcolor"
583 MAYSCRIPT 897 MAYSCRIPT
584 > 898 >
585 $parameters 899 $javaParameters
900
901 Sorry, the Applet could not be started. Please make sure that
902Java 1.4.2 (or later) is installed and activated.
903(<a href="http://java.sun.com/getjava">click here to install Java now</a>)
586 </applet> 904 </applet>
587END_OBJECT_TEXT 905END_OBJECT_TEXT
906
907=cut
908
909# classid = "java:MyApplet.class"
910
911
912use constant DEFAULT_OBJECT_TEXT =><<'END_OBJECT_TEXT';
913
914<object
915 id = "$appletName"
916 name = "$appletName"
917 code = "$code"
918 type = "application/x-java-applet"
919 codebase = "$codebase"
920 archive = "$archive"
921 height = "$height"
922 width = "$width"
923 bgcolor = "$applet_bgcolor"
924 >
925 <PARAM NAME="MAYSCRIPT" VALUE="true">
926 $javaParameters
927
928 Sorry, the Applet could not be started. Please make sure that
929 Java 1.4.2 (or later) is installed and activated.
930 (<a href="http://java.sun.com/getjava">click here to install Java now</a>)
931</object>
932END_OBJECT_TEXT
933
934
588 935
589sub new { 936sub new {
590 my $class = shift; 937 my $class = shift;
591 $class -> SUPER::new( objectText => DEFAULT_OBJECT_TEXT(), 938 $class -> SUPER::new( objectText => DEFAULT_OBJECT_TEXT(),
592 @_ 939 @_
593 ); 940 );
594 941
595} 942}
596 943
944###############################################################################################################
945#
946# CANVAS APPLET PACKAGE
947#
948###############################################################################################################
949
950package CanvasApplet;
951@ISA = qw(Applet);
952
953
954=head2 Insertion HTML code for CanvasApplet
955
956=pod
957
958The secret to making this applet work with IE in addition to normal browsers
959is the addition of the C(<form></form>) construct just before the object.
960
961For some reason IE has trouble locating a flash object which is contained
962within a form. Adding this second blank form with the larger problemMainForm
963seems to solve the problem.
964
965This follows method2 of the advice given in url(http://kb.adobe.com/selfservice/viewContent.do?externalId=kb400730&sliceId=2)
966Method1 and methods involving SWFObject(Geoff Stearns) and SWFFormFix (Steve Kamerman) have yet to be fully investigated:
967http://devel.teratechnologies.net/swfformfix/swfobject_swfformfix_source.js
968http://www.teratechnologies.net/stevekamerman/index.php?m=01&y=07&entry=entry070101-033933
969
970use constant CANVAS_OBJECT_TEXT =><<'END_OBJECT_TEXT';
971 <form></form>
972 <script> var width = 200; var height = 200;</script>
973 <canvas name="cv" id="cv" data-src="http://localhost/webwork2_files/js/sketchgraphhtml5b/SketchGraph.pjs" width="400" height="400"></canvas>
974END_OBJECT_TEXT
975
976
977
978=cut
979
980
981use constant CANVAS_OBJECT_HEADER_TEXT =><<'END_HEADER_SCRIPT';
982 <script src="/webwork2_files/js/Base64.js" language="javascript">
983 </script>
984 <script src="/webwork2_files/js/ww_applet_support.js" language="javascript">
985 //upload functions stored in /opt/webwork/webwork2/htdocs/js ...
986
987 </script>
988 <script language="JavaScript">
989
990
991
992 //////////////////////////////////////////////////////////
993 //CANVAS OBJECT HEADER CODE
994 //
995 //////////////////////////////////////////////////////////
996
997 ww_applet_list["$appletName"] = new ww_applet("$appletName");
998
999
1000 ww_applet_list["$appletName"].code = "$code";
1001 ww_applet_list["$appletName"].codebase = "$codebase";
1002 ww_applet_list["$appletName"].appletID = "$appletID";
1003 ww_applet_list["$appletName"].base64_state = "$base64_initializationState";
1004 ww_applet_list["$appletName"].initialState = Base64.decode("$base64_initialState");
1005 ww_applet_list["$appletName"].configuration = Base64.decode("$base64_configuration");;
1006 ww_applet_list["$appletName"].getStateAlias = "$getStateAlias";
1007 ww_applet_list["$appletName"].setStateAlias = "$setStateAlias";
1008 ww_applet_list["$appletName"].setConfigAlias = "$setConfigAlias";
1009 ww_applet_list["$appletName"].getConfigAlias = "$getConfigAlias";
1010 ww_applet_list["$appletName"].initializeActionAlias = "$initializeActionAlias";
1011 ww_applet_list["$appletName"].submitActionAlias = "$submitActionAlias";
1012 ww_applet_list["$appletName"].submitActionScript = Base64.decode("$base64_submitActionScript");
1013 ww_applet_list["$appletName"].answerBoxAlias = "$answerBoxAlias";
1014 ww_applet_list["$appletName"].maxInitializationAttempts = $maxInitializationAttempts;
1015 ww_applet_list["$appletName"].debugMode = "$debugMode";
1016
1017
1018 ww_applet_list["$appletName"].reportsLoaded = 1;
1019 ww_applet_list["$appletName"].object = $appletName;
1020
1021 function getApplet(appletName) {
1022 //var isIE = navigator.appName.indexOf("Microsoft") != -1;
1023 //var obj = (isIE) ? window[appletName] : window.document[appletName];
1024 //return window.document[appletName];
1025 var obj = ww_applet_list[appletName].object; // define fake applet for this object
1026 if (obj && (obj.name == appletName)) { //RECENT FIX to ==
1027 //alert("getting fake applet " + obj.name);
1028 return( obj );
1029 } else {
1030 alert ("can't find fake applet " + appletName + " in object "+obj.name);
1031 }
1032 }
1033 </script>
1034
1035END_HEADER_SCRIPT
1036
1037
1038#FIXME need to get rid of hardcoded url
1039
1040
1041use constant CANVAS_OBJECT_TEXT =><<'END_OBJECT_TEXT';
1042
1043 <canvas name="cv" id="cv" data-src="/webwork2_files/js/sketchgraphhtml5b/SketchGraph.pjs" width="$width" height="$height"></canvas>
1044END_OBJECT_TEXT
1045
1046sub new {
1047 my $class = shift;
1048 $class -> SUPER::new( objectText => CANVAS_OBJECT_TEXT(),
1049 headerText => CANVAS_OBJECT_HEADER_TEXT(),
1050 @_
1051 );
1052
1053}
597 1054
598 1055
5991; 10561;

Legend:
Removed from v.5622  
changed lines
  Added in v.6324

aubreyja at gmail dot com
ViewVC Help
Powered by ViewVC 1.0.9