jclic 2.2.1 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (177) hide show
  1. package/README.md +5 -7
  2. package/dist-node/jclic-node.js +14157 -0
  3. package/dist-node/jclic-node.umd.cjs +530 -0
  4. package/package.json +38 -26
  5. package/.vscode/launch.json +0 -33
  6. package/.vscode/settings.json +0 -13
  7. package/CHANGELOG.md +0 -672
  8. package/TRANSLATIONS.md +0 -11
  9. package/build-locales.mjs +0 -82
  10. package/dist/jclic-node.js +0 -31680
  11. package/dist/jclic-node.js.map +0 -1
  12. package/dist/jclic.components.LICENSE +0 -2254
  13. package/dist/jclic.min.js +0 -27
  14. package/dist/jclic.min.js.map +0 -1
  15. package/eslint.config.mjs +0 -31
  16. package/jsdoc.config.js +0 -71
  17. package/locales/ar.po +0 -244
  18. package/locales/ast.po +0 -246
  19. package/locales/bs.po +0 -247
  20. package/locales/ca.po +0 -248
  21. package/locales/ca_ES@valencia.po +0 -248
  22. package/locales/cs.po +0 -244
  23. package/locales/da.po +0 -244
  24. package/locales/de.po +0 -246
  25. package/locales/el.po +0 -244
  26. package/locales/es.po +0 -248
  27. package/locales/eu.po +0 -244
  28. package/locales/fr.po +0 -244
  29. package/locales/gl.po +0 -244
  30. package/locales/he.po +0 -244
  31. package/locales/hr.po +0 -245
  32. package/locales/it.po +0 -246
  33. package/locales/ja.po +0 -242
  34. package/locales/jclic.js.pot +0 -241
  35. package/locales/nb_NO.po +0 -244
  36. package/locales/nl.po +0 -244
  37. package/locales/pl.po +0 -244
  38. package/locales/pt.po +0 -244
  39. package/locales/pt_BR.po +0 -248
  40. package/locales/ro.po +0 -248
  41. package/locales/ru.po +0 -245
  42. package/locales/ta.po +0 -244
  43. package/locales/tr.po +0 -246
  44. package/locales/uk.po +0 -247
  45. package/locales/vec.po +0 -244
  46. package/locales/zh_TW.po +0 -246
  47. package/patches/po2json+1.0.0-beta-3.patch +0 -12
  48. package/src/AWT.js +0 -2067
  49. package/src/Activity.js +0 -1311
  50. package/src/Deps.js +0 -232
  51. package/src/GlobalData.js +0 -5
  52. package/src/JClic.js +0 -196
  53. package/src/JClicPlayer.js +0 -1308
  54. package/src/PlayerHistory.js +0 -305
  55. package/src/Utils.js +0 -1355
  56. package/src/activities/associations/ComplexAssociation.js +0 -321
  57. package/src/activities/associations/SimpleAssociation.js +0 -519
  58. package/src/activities/memory/MemoryGame.js +0 -423
  59. package/src/activities/panels/Explore.js +0 -349
  60. package/src/activities/panels/Identify.js +0 -356
  61. package/src/activities/panels/InformationScreen.js +0 -262
  62. package/src/activities/panels/Menu.js +0 -209
  63. package/src/activities/panels/icons/ico00.png +0 -0
  64. package/src/activities/panels/icons/ico01.png +0 -0
  65. package/src/activities/panels/icons/ico02.png +0 -0
  66. package/src/activities/panels/icons/ico03.png +0 -0
  67. package/src/activities/panels/icons/icofolder.png +0 -0
  68. package/src/activities/puzzles/DoublePuzzle.js +0 -424
  69. package/src/activities/puzzles/ExchangePuzzle.js +0 -374
  70. package/src/activities/puzzles/HolePuzzle.js +0 -360
  71. package/src/activities/text/Complete.js +0 -127
  72. package/src/activities/text/Evaluator.js +0 -534
  73. package/src/activities/text/FillInBlanks.js +0 -426
  74. package/src/activities/text/IdentifyText.js +0 -253
  75. package/src/activities/text/OrderText.js +0 -421
  76. package/src/activities/text/TextActivityBase.js +0 -557
  77. package/src/activities/text/TextActivityDocument.js +0 -660
  78. package/src/activities/text/WrittenAnswer.js +0 -557
  79. package/src/activities/textGrid/CrossWord.js +0 -565
  80. package/src/activities/textGrid/WordSearch.js +0 -458
  81. package/src/activities/textGrid/icons/hIcon.svg +0 -3
  82. package/src/activities/textGrid/icons/vIcon.svg +0 -3
  83. package/src/automation/AutoContentProvider.js +0 -182
  84. package/src/automation/arith/Arith.js +0 -864
  85. package/src/bags/ActivitySequence.js +0 -318
  86. package/src/bags/ActivitySequenceElement.js +0 -161
  87. package/src/bags/ActivitySequenceJump.js +0 -140
  88. package/src/bags/ConditionalJumpInfo.js +0 -113
  89. package/src/bags/JumpInfo.js +0 -136
  90. package/src/bags/MediaBag.js +0 -215
  91. package/src/bags/MediaBagElement.js +0 -516
  92. package/src/boxes/AbstractBox.js +0 -699
  93. package/src/boxes/ActiveBagContent.js +0 -494
  94. package/src/boxes/ActiveBox.js +0 -810
  95. package/src/boxes/ActiveBoxBag.js +0 -357
  96. package/src/boxes/ActiveBoxContent.js +0 -484
  97. package/src/boxes/ActiveBoxGrid.js +0 -179
  98. package/src/boxes/BoxBag.js +0 -500
  99. package/src/boxes/BoxBase.js +0 -398
  100. package/src/boxes/BoxConnector.js +0 -325
  101. package/src/boxes/TextGrid.js +0 -887
  102. package/src/boxes/TextGridContent.js +0 -215
  103. package/src/init-jsdom.js +0 -65
  104. package/src/jclic-node.js +0 -219
  105. package/src/media/ActiveMediaBag.js +0 -145
  106. package/src/media/ActiveMediaPlayer.js +0 -297
  107. package/src/media/AudioBuffer.js +0 -219
  108. package/src/media/EventSounds.js +0 -169
  109. package/src/media/EventSoundsElement.js +0 -155
  110. package/src/media/MediaContent.js +0 -328
  111. package/src/media/MidiAudioPlayer.js +0 -254
  112. package/src/media/icons/audio.svg +0 -3
  113. package/src/media/icons/generic.svg +0 -3
  114. package/src/media/icons/mic.svg +0 -3
  115. package/src/media/icons/movie.svg +0 -3
  116. package/src/media/icons/music.svg +0 -3
  117. package/src/media/icons/url.svg +0 -3
  118. package/src/media/sounds/actionError.mp3 +0 -0
  119. package/src/media/sounds/actionOk.mp3 +0 -0
  120. package/src/media/sounds/click.mp3 +0 -0
  121. package/src/media/sounds/finishedError.mp3 +0 -0
  122. package/src/media/sounds/finishedOk.mp3 +0 -0
  123. package/src/media/sounds/start.mp3 +0 -0
  124. package/src/project/JClicProject.js +0 -282
  125. package/src/project/ProjectSettings.js +0 -273
  126. package/src/report/ActionReg.js +0 -123
  127. package/src/report/ActivityReg.js +0 -271
  128. package/src/report/EncryptMin.js +0 -210
  129. package/src/report/Reporter.js +0 -727
  130. package/src/report/SCORM.js +0 -272
  131. package/src/report/SequenceReg.js +0 -275
  132. package/src/report/SessionReg.js +0 -340
  133. package/src/report/SessionStorageReporter.js +0 -131
  134. package/src/report/TCPReporter.js +0 -628
  135. package/src/shapers/ClassicJigSaw.js +0 -138
  136. package/src/shapers/Holes.js +0 -77
  137. package/src/shapers/JigSaw.js +0 -161
  138. package/src/shapers/Rectangular.js +0 -78
  139. package/src/shapers/Shaper.js +0 -386
  140. package/src/shapers/TriangularJigSaw.js +0 -121
  141. package/src/skins/BlueSkin.js +0 -80
  142. package/src/skins/Counter.js +0 -152
  143. package/src/skins/CustomSkin.js +0 -412
  144. package/src/skins/DefaultSkin.js +0 -376
  145. package/src/skins/EmptySkin.js +0 -82
  146. package/src/skins/GreenSkin.js +0 -94
  147. package/src/skins/MiniSkin.js +0 -130
  148. package/src/skins/OrangeSkin.js +0 -78
  149. package/src/skins/SimpleSkin.js +0 -92
  150. package/src/skins/Skin.js +0 -1021
  151. package/src/skins/assets/actionsIcon.svg +0 -3
  152. package/src/skins/assets/appLogo.svg +0 -8
  153. package/src/skins/assets/basic.css +0 -41
  154. package/src/skins/assets/closeDialogIcon.svg +0 -3
  155. package/src/skins/assets/closeIcon.svg +0 -3
  156. package/src/skins/assets/copyIcon.svg +0 -3
  157. package/src/skins/assets/fullScreenExitIcon.svg +0 -3
  158. package/src/skins/assets/fullScreenIcon.svg +0 -3
  159. package/src/skins/assets/infoIcon.svg +0 -3
  160. package/src/skins/assets/main.css +0 -43
  161. package/src/skins/assets/mainHalf.css +0 -23
  162. package/src/skins/assets/mainTwoThirds.css +0 -23
  163. package/src/skins/assets/mini.css +0 -15
  164. package/src/skins/assets/nextIcon.svg +0 -3
  165. package/src/skins/assets/okDialogIcon.svg +0 -3
  166. package/src/skins/assets/prevIcon.svg +0 -3
  167. package/src/skins/assets/reports.css +0 -156
  168. package/src/skins/assets/reportsIcon.svg +0 -3
  169. package/src/skins/assets/scoreIcon.svg +0 -3
  170. package/src/skins/assets/simple.css +0 -16
  171. package/src/skins/assets/simpleHalf.css +0 -11
  172. package/src/skins/assets/simpleTwoThirds.css +0 -11
  173. package/src/skins/assets/timeIcon.svg +0 -4
  174. package/src/skins/assets/waitAnim.css +0 -54
  175. package/src/skins/assets/waitImgBig.svg +0 -3
  176. package/src/skins/assets/waitImgSmall.svg +0 -3
  177. package/webpack.config.mjs +0 -169
package/src/Activity.js DELETED
@@ -1,1311 +0,0 @@
1
- /**
2
- * File : Activity.js
3
- * Created : 07/04/2015
4
- * By : Francesc Busquets <francesc@gmail.com>
5
- *
6
- * JClic.js
7
- * An HTML5 player of JClic activities
8
- * https://projectestac.github.io/jclic.js
9
- *
10
- * @source https://github.com/projectestac/jclic.js
11
- *
12
- * @license EUPL-1.2
13
- * @licstart
14
- * (c) 2000-2020 Educational Telematic Network of Catalonia (XTEC)
15
- *
16
- * Licensed under the EUPL, Version 1.1 or -as soon they will be approved by
17
- * the European Commission- subsequent versions of the EUPL (the "Licence");
18
- * You may not use this work except in compliance with the Licence.
19
- *
20
- * You may obtain a copy of the Licence at:
21
- * https://joinup.ec.europa.eu/software/page/eupl
22
- *
23
- * Unless required by applicable law or agreed to in writing, software
24
- * distributed under the Licence is distributed on an "AS IS" basis, WITHOUT
25
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
26
- * Licence for the specific language governing permissions and limitations
27
- * under the Licence.
28
- * @licend
29
- * @module
30
- */
31
-
32
- /* global window */
33
-
34
- import $ from 'jquery';
35
- import { settings, log, getMsg, attrForEach, nSlash, getBoolean, getXmlText, checkColor, isNullOrUndef, getAttr, setAttr } from './Utils.js';
36
- import { Rectangle, Gradient, Point, Dimension, Container } from './AWT.js';
37
- import EventSounds from './media/EventSounds.js';
38
- import ActiveBoxContent from './boxes/ActiveBoxContent.js';
39
- import ActiveBagContent from './boxes/ActiveBagContent.js';
40
- import BoxBase from './boxes/BoxBase.js';
41
- import AutoContentProvider from './automation/AutoContentProvider.js';
42
- import TextGridContent from './boxes/TextGridContent.js';
43
- import Evaluator from './activities/text/Evaluator.js';
44
- import TextActivityDocument from './activities/text/TextActivityDocument.js';
45
-
46
- // Event used for detecting touch devices
47
- const TOUCH_TEST_EVENT = 'touchstart';
48
-
49
- /**
50
- * Activity is the abstract base class of JClic activities. It defines also the inner class
51
- * {@link module:Activity.ActivityPanel ActivityPanel}, wich is responsible for user interaction with the activity
52
- * content.
53
- * Activities should extend both `Activity` and `ActivityPanel` classes in order to become fully
54
- * operative.
55
- * @abstract
56
- */
57
- export class Activity {
58
- /**
59
- * Activity constructor
60
- * @param {module:project/JClicProject.JClicProject} project - The {@link module:project/JClicProject.JClicProject JClicProject} to which this activity belongs
61
- */
62
- constructor(project) {
63
- this.project = project;
64
- this.eventSounds = new EventSounds(this.project.settings.eventSounds);
65
- this.messages = {};
66
- this.abc = {};
67
- }
68
-
69
- /**
70
- * Registers a new type of activity
71
- * @param {string} activityName - The name used to identify this activity
72
- * @param {function} activityClass - The activity class, usually extending Activity
73
- * @returns {module:Activity.Activity} - The provided activity class
74
- */
75
- static registerClass(activityName, activityClass) {
76
- Activity.CLASSES[activityName] = activityClass;
77
- return activityClass;
78
- }
79
-
80
- /**
81
- * Factory constructor that returns a specific type of Activity based on the `class` attribute
82
- * declared in `data`.
83
- * @param {object|external:jQuery} data - Can be a jQuery XML element, or an object obtained with a call to `getAttributes`
84
- * @param {module:project/JClicProject.JClicProject} project - The {@link module:project/JClicProject.JClicProject JClicProject} to which this activity belongs
85
- * @returns {module:Activity.Activity}
86
- */
87
- static getActivity(data, project) {
88
- let act = null;
89
- const isXml = data.jquery && true;
90
- if (data && project) {
91
- const className = isXml ? (data.attr('class') || '').replace(/^edu\.xtec\.jclic\.activities\./, '@') : data.className;
92
- const cl = Activity.CLASSES[className];
93
- if (cl) {
94
- act = new cl(project);
95
- if (isXml)
96
- act.setProperties(data);
97
- else
98
- act.setAttributes(data);
99
- } else
100
- log('error', `Unknown activity class: ${className}`);
101
- }
102
- return act;
103
- }
104
-
105
- /**
106
- * Loads this object settings from an XML element
107
- * @param {external:jQuery} $xml - The jQuery XML element to parse
108
- */
109
- setProperties($xml) {
110
-
111
- // Read attributes
112
- attrForEach($xml.get(0).attributes, (name, val) => {
113
- switch (name) {
114
- // Generic attributes:
115
- case 'name':
116
- val = nSlash(val);
117
- /* falls through */
118
- case 'code':
119
- case 'type':
120
- case 'description':
121
- this[name] = val;
122
- break;
123
-
124
- case 'class':
125
- this.className = val.replace(/^edu\.xtec\.jclic\.activities\./, '@');
126
- break;
127
-
128
- case 'inverse':
129
- this.invAss = getBoolean(val, false);
130
- break;
131
-
132
- case 'autoJump':
133
- case 'forceOkToAdvance':
134
- case 'amongParagraphs':
135
- this[name] = getBoolean(val, false);
136
- break;
137
- }
138
- });
139
-
140
- // Read specific nodes
141
- $xml.children().each((_n, child) => {
142
- const $node = $(child);
143
- switch (child.nodeName) {
144
- case 'settings':
145
- // Read more attributes
146
- attrForEach($node.get(0).attributes, (name, val) => {
147
- switch (name) {
148
- case 'infoUrl':
149
- case 'infoCmd':
150
- this[name] = val;
151
- break;
152
-
153
- case 'margin':
154
- case 'maxTime':
155
- case 'maxActions':
156
- this[name] = Number(val);
157
- break;
158
-
159
- case 'report':
160
- this.includeInReports = getBoolean(val, false);
161
- break;
162
- case 'countDownTime':
163
- case 'countDownActions':
164
- case 'reportActions':
165
- case 'useOrder':
166
- case 'dragCells':
167
- this[name] = getBoolean(val, false);
168
- break;
169
- }
170
- });
171
-
172
- // Read elements of _settings_
173
- $node.children().each((_n, child) => {
174
- const $node = $(child);
175
- switch (child.nodeName) {
176
- case 'skin':
177
- this.skinFileName = $node.attr('file');
178
- break;
179
-
180
- case 'helpWindow':
181
- this.helpMsg = getXmlText(this);
182
- this.showSolution = getBoolean($node.attr('showSolution'), false);
183
- this.helpWindow = this.helpMsg !== null || this.showSolution;
184
- break;
185
-
186
- case 'container':
187
- // Read settings related to the 'container'
188
- // (the main panel containing the activity and other elements)
189
- this.bgColor = checkColor($node.attr('bgColor'), settings.BoxBase.BACK_COLOR);
190
-
191
- $node.children().each((_n, child) => {
192
- const $child = $(child);
193
- switch (child.nodeName) {
194
- case 'image':
195
- this.bgImageFile = $child.attr('name');
196
- this.tiledBgImg = getBoolean($child.attr('tiled'), false);
197
- break;
198
- case 'counters':
199
- this.bTimeCounter = getBoolean($child.attr('time'), true);
200
- this.bActionsCounter = getBoolean($child.attr('actions'), true);
201
- this.bScoreCounter = getBoolean($child.attr('score'), true);
202
- break;
203
- case 'gradient':
204
- this.bgGradient = new Gradient().setProperties($child);
205
- break;
206
- }
207
- });
208
- break;
209
-
210
- case 'window':
211
- // Read settings related to the 'window'
212
- // (the panel where the activity deploys its content)
213
- this.activityBgColor = checkColor($node.attr('bgColor'), settings.DEFAULT_BG_COLOR);
214
- this.transparentBg = getBoolean($node.attr('transparent'), false);
215
- this.border = getBoolean($node.attr('border'), false);
216
- $node.children().each((_n, child) => {
217
- const $child = $(child);
218
- switch (child.nodeName) {
219
- case 'gradient':
220
- this.activityBgGradient = new Gradient().setProperties($child);
221
- break;
222
- case 'position':
223
- this.absolutePosition = new Point().setProperties($child);
224
- this.absolutePositioned = true;
225
- break;
226
- case 'size':
227
- this.windowSize = new Dimension().setProperties($child);
228
- break;
229
- }
230
- });
231
- break;
232
-
233
- case 'eventSounds':
234
- // eventSounds is already created in constructor,
235
- // just read properties
236
- this.eventSounds.setProperties($node);
237
- break;
238
- }
239
- });
240
- break;
241
-
242
- case 'messages':
243
- $node.children('cell').each((_n, child) => {
244
- const m = this.readMessage($(child));
245
- // Possible message types are: `initial`, `final`, `previous`, `finalError`
246
- this.messages[m.type] = m;
247
- });
248
- break;
249
-
250
- case 'automation':
251
- // Read the automation settings ('Arith' or other automation engines)
252
- this.acp = AutoContentProvider.getProvider($node, this.project);
253
- if (this.acp)
254
- this.numericContent = this.acp.numericContent;
255
- break;
256
-
257
- // Settings specific to panel-type activities (puzzles, associations...)
258
- case 'cells':
259
- // Read the [ActiveBagContent](ActiveBagContent.html) objects
260
- const cellSet = new ActiveBagContent().setProperties($node, this.project.mediaBag);
261
- // Valid ids:
262
- // - Panel activities: 'primary', 'secondary', solvedPrimary'
263
- // - Textpanel activities: 'acrossClues', 'downClues', 'answers'
264
- this.abc[cellSet.id] = cellSet;
265
- break;
266
-
267
- case 'scramble':
268
- // Read the 'shuffle' mode
269
- this.shuffles = Number($node.attr('times'));
270
- this.shuffleA = getBoolean($node.attr('primary'));
271
- this.shuffleB = getBoolean($node.attr('secondary'));
272
- break;
273
-
274
- case 'layout':
275
- attrForEach($node.get(0).attributes, (name, value) => {
276
- switch (name) {
277
- case 'position':
278
- this.boxGridPos = value;
279
- break;
280
- case 'wildTransparent':
281
- case 'upperCase':
282
- case 'checkCase':
283
- this[name] = getBoolean(value);
284
- }
285
- });
286
- break;
287
-
288
- // Element specific to 'Menu' activities:
289
- case 'menuElement':
290
- this.menuElements.push({
291
- caption: $node.attr('caption') || '',
292
- icon: $node.attr('icon') || null,
293
- projectPath: $node.attr('path') || null,
294
- sequence: $node.attr('sequence') || null,
295
- description: $node.attr('description') || ''
296
- });
297
- break;
298
-
299
- // Element specific to 'CrossWord' and
300
- // 'WordSearch' activities:
301
- case 'textGrid':
302
- // Read the 'textGrid' element into a 'TextGridContent'
303
- this.tgc = new TextGridContent().setProperties($node);
304
- break;
305
-
306
- // Read the clues of 'WordSearch' activities
307
- case 'clues':
308
- // Read the array of clues
309
- this.clues = [];
310
- this.clueItems = [];
311
- $node.children('clue').each((n, child) => {
312
- this.clueItems[n] = Number($(child).attr('id'));
313
- this.clues[n] = child.textContent;
314
- });
315
- break;
316
-
317
- // Elements specific to text activities:
318
- case 'checkButton':
319
- this.checkButtonText = child.textContent || 'check';
320
- break;
321
-
322
- case 'prevScreen':
323
- this.prevScreen = true;
324
- this.prevScreenMaxTime = $node.attr('maxTime') || -1;
325
- $node.children().each((_n, child) => {
326
- switch (child.nodeName) {
327
- case 'style':
328
- this.prevScreenStyle = new BoxBase().setProperties($(child));
329
- break;
330
- case 'p':
331
- if (this.prevScreenText === null)
332
- this.prevScreenText = '';
333
- this.prevScreenText += `<p>${child.textContent}</p>`;
334
- break;
335
- }
336
- });
337
- break;
338
-
339
- case 'evaluator':
340
- this.ev = Evaluator.getEvaluator($node);
341
- break;
342
-
343
- case 'document':
344
- // Read main document of text activities
345
- this.document = new TextActivityDocument().setProperties($node, this.project.mediaBag);
346
- break;
347
- }
348
- });
349
- return this;
350
- }
351
-
352
- /**
353
- * Read an activity message from an XML element
354
- * @param {external:jQuery} $xml - The XML element to be parsed
355
- * @returns {module:boxes/ActiveBoxContent.ActiveBoxContent}
356
- */
357
- readMessage($xml) {
358
- const msg = new ActiveBoxContent().setProperties($xml, this.project.mediaBag);
359
- //
360
- // Allowed types are: `initial`, `final`, `previous`, `finalError`
361
- msg.type = $xml.attr('type');
362
- if (isNullOrUndef(msg.style))
363
- msg.style = new BoxBase(null);
364
- return msg;
365
- }
366
-
367
- /**
368
- * Gets a object with the basic attributes needed to rebuild this instance excluding functions,
369
- * parent references, constants and also attributes retaining the default value.
370
- * The resulting object is commonly usued to serialize elements in JSON format.
371
- * @returns {object} - The resulting object, with minimal attrributes
372
- */
373
- getAttributes() {
374
- return getAttr(this, [
375
- 'name', 'className', 'code', 'type', 'description',
376
- 'invAss', 'numericContent',
377
- 'autoJump', 'forceOkToAdvance', 'amongParagraphs',
378
- 'infoUrl', 'infoCmd',
379
- `margin|${settings.DEFAULT_MARGIN}`, 'maxTime', 'maxActions',
380
- 'includeInReports|true', 'reportActions|false',
381
- 'countDownTime', 'countDownActions',
382
- 'useOrder', 'dragCells',
383
- 'skinFileName',
384
- 'showSolution|false', 'helpMsg',
385
- `bgColor|${settings.DEFAULT_BG_COLOR}`, 'bgImageFile', 'tiledBgImg',
386
- 'bTimeCounter|true', 'bActionsCounter|true', 'bScoreCounter|true',
387
- `activityBgColor|${settings.DEFAULT_BG_COLOR}`, 'transparentBg|false', 'border|true',
388
- 'shuffleA', 'shuffleB', 'shuffles', 'boxGridPos',
389
- 'wildTransparent', 'upperCase', 'checkCase',
390
- 'checkButtonText',
391
- 'prevScreen', 'prevScreenMaxTime', 'prevScreenText',
392
- 'bgGradient', 'activityBgGradient', // Gradient
393
- 'absolutePosition', // Point
394
- 'windowSize', // Dimension
395
- 'eventSounds', // EventSounds
396
- 'messages', // ActiveBoxContent{}
397
- 'acp', // AutoContentProvider
398
- 'abc', // ActiveBagContent{}
399
- 'menuElements', // Activity~menuElement
400
- 'tgc', // TextGridContent
401
- 'clues', // string[]
402
- 'clueItems', // number[]
403
- 'prevScreenStyle', // BoxBase
404
- 'ev', // Evaluator
405
- 'document', // TextActivityDocument
406
- ]);
407
- }
408
-
409
- /**
410
- * Load the activity settings from a data object
411
- * @param {object} data - The data object to parse
412
- */
413
- setAttributes(data, mediaBag = this.project.mediaBag) {
414
- setAttr(this, data, [
415
- 'name', 'className', 'code', 'type', 'description', 'invAss', 'numericContent',
416
- 'autoJump', 'forceOkToAdvance', 'amongParagraphs', 'infoUrl', 'infoCmd',
417
- 'margin', 'maxTime', 'maxActions', 'includeInReports', 'reportActions',
418
- 'countDownTime', 'countDownActions', 'useOrder', 'dragCells', 'skinFileName',
419
- 'showSolution', 'helpMsg', 'bgColor', 'bgImageFile', 'tiledBgImg',
420
- 'bTimeCounter', 'bActionsCounter', 'bScoreCounter',
421
- 'activityBgColor', 'transparentBg', 'border',
422
- 'shuffleA', 'shuffleB', 'shuffles', 'boxGridPos',
423
- 'wildTransparent', 'upperCase', 'checkCase', 'checkButtonText',
424
- 'prevScreen', 'prevScreenMaxTime', 'prevScreenText',
425
- { key: 'bgGradient', fn: Gradient },
426
- { key: 'activityBgGradient', fn: Gradient },
427
- { key: 'absolutePosition', fn: Point },
428
- { key: 'windowSize', fn: Dimension },
429
- { key: 'messages', fn: ActiveBoxContent, group: 'object', init: 'key', params: [mediaBag] },
430
- { key: 'abc', fn: ActiveBagContent, group: 'object', init: 'key', params: [mediaBag] },
431
- { key: 'acp', fn: AutoContentProvider, params: [mediaBag] },
432
- 'menuElements',
433
- { key: 'tgc', fn: TextGridContent },
434
- 'clues',
435
- 'clueItems',
436
- { key: 'prevScreenStyle', fn: BoxBase },
437
- { key: 'ev', fn: Evaluator },
438
- { key: 'document', fn: TextActivityDocument, params: [mediaBag] },
439
- ]);
440
-
441
- // Reused objects
442
- if (data.eventSounds)
443
- this.eventSounds.setAttributes(data.eventSounds);
444
-
445
- // Manual settings
446
- if (this.absolutePosition)
447
- this.absolutePositioned = true;
448
-
449
- return this;
450
- }
451
-
452
- /**
453
- * Initialises the {@link module:automation/AutoContentProvider.AutoContentProvider AutoContentProvider}, when defined.
454
- */
455
- initAutoContentProvider() {
456
- if (this.acp !== null)
457
- this.acp.init();
458
- }
459
-
460
- /**
461
- * Preloads the media content of the activity.
462
- * @param {module:JClicPlayer.JClicPlayer} ps - The {@link module:JClicPlayer.JClicPlayer} used to realize the media objects.
463
- */
464
- prepareMedia(ps) {
465
- this.eventSounds.realize(ps, this.project.mediaBag);
466
- $.each(this.messages, (_key, msg) => {
467
- if (msg !== null) msg.prepareMedia(ps);
468
- });
469
- $.each(this.abc, (_key, abc) => {
470
- if (abc !== null)
471
- abc.prepareMedia(ps);
472
- });
473
- return true;
474
- }
475
-
476
- /**
477
- * Whether the activity allows the user to request the solution.
478
- * @returns {boolean}
479
- */
480
- helpSolutionAllowed() {
481
- return false;
482
- }
483
-
484
- /**
485
- * Whether the activity allows the user to request help.
486
- * @returns {boolean}
487
- */
488
- helpWindowAllowed() {
489
- return this.helpWindow &&
490
- (this.helpSolutionAllowed() && this.showSolution || this.helpMsg !== null);
491
- }
492
-
493
- /**
494
- * Retrieves the minimum number of actions needed to solve this activity.
495
- * @returns {number}
496
- */
497
- getMinNumActions() {
498
- return 0;
499
- }
500
-
501
- /**
502
- * When this method returns `true`, the automatic jump to the next activity must be paused at
503
- * this activity.
504
- * @returns {boolean}
505
- */
506
- mustPauseSequence() {
507
- return this.getMinNumActions() !== 0;
508
- }
509
-
510
- /**
511
- * Whether or not the activity can be reset
512
- * @returns {boolean}
513
- */
514
- canReinit() {
515
- return true;
516
- }
517
-
518
- /**
519
- * Whether or not the activity has additional information to be shown.
520
- * @returns {boolean}
521
- */
522
- hasInfo() {
523
- return this.infoUrl !== null && this.infoUrl.length > 0 ||
524
- this.infoCmd !== null && this.infoCmd.length > 0;
525
- }
526
-
527
- /**
528
- * Whether or not the activity uses random to shuffle internal components
529
- * @returns {boolean}
530
- */
531
- hasRandom() {
532
- return false;
533
- }
534
-
535
- /**
536
- * When `true`, the activity must always be shuffled
537
- * @returns {boolean}
538
- */
539
- shuffleAlways() {
540
- return false;
541
- }
542
-
543
- /**
544
- * When `true`, the activity makes use of the keyboard
545
- * @returns {boolean}
546
- */
547
- needsKeyboard() {
548
- return false;
549
- }
550
-
551
- /**
552
- * Called when the activity must be disposed
553
- */
554
- end() {
555
- this.eventSounds.close();
556
- this.clear();
557
- }
558
-
559
- /**
560
- * Called when the activity must reset its internal components
561
- */
562
- clear() {
563
- }
564
-
565
- /**
566
- *
567
- * Getter method for `windowSize`
568
- * @returns {module:AWT.Dimension}
569
- */
570
- getWindowSize() {
571
- return new Dimension(this.windowSize);
572
- }
573
-
574
- /**
575
- * Setter method for `windowSize`
576
- * @param {module:AWT.Dimension} windowSize
577
- */
578
- setWindowSize(windowSize) {
579
- this.windowSize = new Dimension(windowSize);
580
- }
581
-
582
- /**
583
- * Builds the {@link module:Activity.ActivityPanel ActivityPanel} object.
584
- * Subclasses must update the `Panel` member of its prototypes to produce specific panels.
585
- * @param {module:JClicPlayer.JClicPlayer} ps - The {@link module:JClicPlayer.JClicPlayer JClicPlayer} used to build media objects.
586
- * @returns {module:Activity.ActivityPanel}
587
- */
588
- getActivityPanel(ps) {
589
- return new this.constructor.Panel(this, ps);
590
- }
591
- }
592
-
593
- /**
594
- * Classes derived from `Activity` should register themselves by adding a field to
595
- * `Activity.CLASSES` using `Activity.registerClass`
596
- * @type {object}
597
- */
598
- Activity.CLASSES = {
599
- '@panels.Menu': Activity
600
- };
601
-
602
- Object.assign(Activity.prototype, {
603
- /**
604
- * The {@link module:project/JClicProject.JClicProject JClicProject} to which this activity belongs
605
- * @name module:Activity.Activity#project
606
- * @type {module:project/JClicProject.JClicProject} */
607
- project: null,
608
- /**
609
- * The Activity name
610
- * @name module:Activity.Activity#name
611
- * @type {string} */
612
- name: settings.DEFAULT_NAME,
613
- /**
614
- * The class name of this Activity
615
- * @name module:Activity.Activity#className
616
- * @type {string} */
617
- className: null,
618
- /**
619
- * Code used in reports to filter queries. Default is `null`.
620
- * @name module:Activity.Activity#code
621
- * @type {string} */
622
- code: null,
623
- /**
624
- * Type of activity, used in text activities to distinguish between different variants of the
625
- * same activity. Possible values are: `orderWords`, `orderParagraphs`, `identifyWords` and
626
- * `identifyChars`.
627
- * @name module:Activity.Activity#type
628
- * @type {string} */
629
- type: null,
630
- /**
631
- * A short description of the activity
632
- * @name module:Activity.Activity#description
633
- * @type {string} */
634
- description: null,
635
- /**
636
- * The space between the activity components measured in pixels.
637
- * @name module:Activity.Activity#margin
638
- * @type {number} */
639
- margin: settings.DEFAULT_MARGIN,
640
- /**
641
- * The background color of the activity panel
642
- * @name module:Activity.Activity#bgColor
643
- * @type {string} */
644
- bgColor: settings.DEFAULT_BG_COLOR,
645
- /**
646
- * When set, gradient used to draw the activity window background
647
- * @name module:Activity.Activity#bgGradient
648
- * @type {module:AWT.Gradient} */
649
- bgGradient: null,
650
- /**
651
- * Whether the bgImage (if any) has to be tiled across the panel background
652
- * @name module:Activity.Activity#tiledBgImg
653
- * @type {boolean} */
654
- tiledBgImg: false,
655
- /**
656
- * Filename of the image used as a panel background.
657
- * @name module:Activity.Activity#bgImageFile
658
- * @type {string} */
659
- bgImageFile: null,
660
- /**
661
- * Whether to draw a border around the activity panel
662
- * @name module:Activity.Activity#border
663
- * @type {boolean} */
664
- border: true,
665
- /**
666
- * Whether to place the activity panel at the point specified by `absolutePosition` or leave
667
- * it centered on the main player's window.
668
- * @name module:Activity.Activity#absolutePositioned
669
- * @type {boolean} */
670
- absolutePositioned: false,
671
- /**
672
- * The position of the activity panel on the player.
673
- * @name module:Activity.Activity#absolutePosition
674
- * @type {module:AWT.Point} */
675
- absolutePosition: null,
676
- /**
677
- * Whether to generate usage reports
678
- * @name module:Activity.Activity#includeInReports
679
- * @type {boolean} */
680
- includeInReports: true,
681
- /**
682
- * Whether to send action events to the {@link module:Reporter.Reporter Reporter}
683
- * @name module:Activity.Activity#reportActions
684
- * @type {boolean} */
685
- reportActions: false,
686
- /**
687
- * Whether to allow help about the activity or not.
688
- * @name module:Activity.Activity#helpWindow
689
- * @type {boolean} */
690
- helpWindow: false,
691
- /**
692
- * Whether to show the solution on the help window.
693
- * @name module:Activity.Activity#showSolution
694
- * @type {boolean} */
695
- showSolution: false,
696
- /**
697
- * Message to be shown in the help window when `showSolution` is `false`.
698
- * @name module:Activity.Activity#helpMsg
699
- * @type {string} */
700
- helpMsg: '',
701
- /**
702
- * Specific set of {@link module:media/EventSounds.EventSounds EventSounds} used in the activity. The default is `null`, meaning
703
- * to use the default event sounds.
704
- * @name module:Activity.Activity#eventSounds
705
- * @type {module:media/EventSounds.EventSounds} */
706
- eventSounds: null,
707
- /**
708
- * Wheter the activity must be solved in a specific order or not.
709
- * @name module:Activity.Activity#useOrder
710
- * @type {boolean} */
711
- useOrder: false,
712
- /**
713
- * Wheter the cells of the activity will be dragged across the screen.
714
- * When `false`, a line will be painted to link elements.
715
- * @name module:Activity.Activity#dragCells
716
- * @type {boolean} */
717
- dragCells: false,
718
- /**
719
- * File name of the Skin used by the activity. The default value is `null`, meaning that the
720
- * activity will use the skin specified for the project.
721
- * @name module:Activity.Activity#skinFileName
722
- * @type {string} */
723
- skinFileName: null,
724
- /**
725
- * Maximum amount of time (seconds) to solve the activity. The default value is 0, meaning
726
- * unlimited time.
727
- * @name module:Activity.Activity#maxTime
728
- * @type {number}*/
729
- maxTime: 0,
730
- /**
731
- * Whether the time counter should display a countdown when `maxTime > 0`
732
- * @name module:Activity.Activity#countDownTime
733
- * @type {boolean} */
734
- countDownTime: false,
735
- /**
736
- * Maximum number of actions allowed to solve the activity. The default value is 0, meaning
737
- * unlimited actions.
738
- * @name module:Activity.Activity#maxActions
739
- * @type {number}*/
740
- maxActions: 0,
741
- /**
742
- * Whether the actions counter should display a countdown when `maxActions > 0`
743
- * @name module:Activity.Activity#countDownActions
744
- * @type {boolean} */
745
- countDownActions: false,
746
- /**
747
- * URL to be launched when the user clicks on the 'info' button. Default is `null`.
748
- * @name module:Activity.Activity#infoUrl
749
- * @type {string} */
750
- infoUrl: null,
751
- /**
752
- * System command to be launched when the user clicks on the 'info' button. Default is `null`.
753
- * Important: this parameter is currently not being used
754
- * @name module:Activity.Activity#infoCmd
755
- * @type {string} */
756
- infoCmd: null,
757
- /**
758
- * The content of the initial, final, previous and error messages shown by the activity.
759
- * @name module:Activity.Activity#messages
760
- * @type {module:boxes/ActiveBoxContent.ActiveBoxContent[]} */
761
- messages: null,
762
- /**
763
- * Preferred dimension of the activity window
764
- * @name module:Activity.Activity#windowSize
765
- * @type {module:AWT.Dimension} */
766
- windowSize: new Dimension(settings.DEFAULT_WIDTH, settings.DEFAULT_HEIGHT),
767
- /**
768
- * Whether the activity window has transparent background.
769
- * @name module:Activity.Activity#transparentBg
770
- * @type {boolean} */
771
- transparentBg: false,
772
- /**
773
- * The background color of the activity
774
- * @name module:Activity.Activity#activityBgColor
775
- * @type {string} */
776
- activityBgColor: settings.DEFAULT_BG_COLOR,
777
- /**
778
- * Gradient used to draw backgrounds inside the activity.
779
- * @name module:Activity.Activity#activityBgGradient
780
- * @type {module:AWT.Gradient} */
781
- activityBgGradient: null,
782
- /**
783
- * Whether to display or not the 'time' counter
784
- * @name module:Activity.Activity#bTimeCounter
785
- * @type {boolean} */
786
- bTimeCounter: true,
787
- /**
788
- * Whether to display or not the 'score' counter
789
- * @name module:Activity.Activity#bScoreCounter
790
- * @type {boolean} */
791
- bScoreCounter: true,
792
- /**
793
- * Whether to display or not the 'actions' counter
794
- * @name module:Activity.Activity#bActionsCounter
795
- * @type {boolean} */
796
- bActionsCounter: true,
797
- /**
798
- * Special object used to generate random content at the start of the activity
799
- * @name module:Activity.Activity#acp
800
- * @type {module:automation/AutoContentProvider.AutoContentProvider} */
801
- acp: null,
802
- //
803
- // Fields used only in certain activity types
804
- // ------------------------------------------
805
- //
806
- /**
807
- * Array of bags with the description of the content to be displayed on panels and cells.
808
- * @name module:Activity.Activity#abc
809
- * @type {module:boxes/ActiveBagContent.ActiveBagContent[]} */
810
- abc: null,
811
- /**
812
- * Content of the grid of letters used in crosswords and shuffled letters
813
- * @name module:Activity.Activity#tgc
814
- * @type {module:boxes/TextGridContent.TextGridContent} */
815
- tgc: null,
816
- /**
817
- * The main document used in text activities
818
- * @name module:Activity.Activity#document
819
- * @type {module:activities/text/TextActivityDocument.TextActivityDocument} */
820
- document: null,
821
- /**
822
- * Relative position of the text grid (uses the same position codes as box grids)
823
- * @name module:Activity.Activity#boxGridPos
824
- * @type {string} */
825
- boxGridPos: 'AB',
826
- /**
827
- * Number of times to shuffle the cells at the beginning of the activity
828
- * @name module:Activity.Activity#shuffles
829
- * @type {number} */
830
- shuffles: settings.DEFAULT_SHUFFLES,
831
- /**
832
- * Box grid A must be shuffled.
833
- * @name module:Activity.Activity#shuffleA
834
- * @type {boolean} */
835
- shuffleA: true,
836
- /**
837
- * Box grid B must be shuffled.
838
- * @name module:Activity.Activity#shuffleB
839
- * @type {boolean} */
840
- shuffleB: true,
841
- /**
842
- * Flag to indicate "inverse resolution" in complex associations
843
- * @name module:Activity.Activity#invAss
844
- * @type {boolean} */
845
- invAss: false,
846
- /**
847
- * Array of menu elements, used in activities of type {@link module:activities/panels/Menu.Menu Menu}
848
- * @name module:Activity.Activity#menuElements
849
- * @type {object[]} */
850
- menuElements: null,
851
- /**
852
- * This activity uses numeric expressions, so text literals should be
853
- * converted to numbers for comparisions, taking in account the
854
- * number format of the current locale (dot or comma as decimal separator)
855
- * @name module:Activity.Activity#numericContent
856
- * @type {boolean} */
857
- numericContent: false,
858
- });
859
-
860
- /**
861
- * This object is responsible for rendering the contents of the activity on the screen and
862
- * managing user's interaction.
863
- * Each type of Activity must implement its own `ActivityPanel`.
864
- * In JClic, {@link http://projectestac.github.io/jclic/apidoc/edu/xtec/jclic/Activity.Panel.html Activity.Panel}
865
- * extends {@link http://docs.oracle.com/javase/7/docs/api/javax/swing/JPanel.html javax.swing.JPanel}.
866
- * On this implementation, the JPanel will be replaced by an HTML `div` tag.
867
- * @extends module:AWT.Container
868
- */
869
- export class ActivityPanel extends Container {
870
- /**
871
- * ActivityPanel constructor
872
- * @param {module:Activity.Activity} act - The {@link module:Activity.Activity Activity} to which this Panel belongs
873
- * @param {module:JClicPlayer.JClicPlayer} ps - Any object implementing the methods defined in the
874
- * {@link http://projectestac.github.io/jclic/apidoc/edu/xtec/jclic/PlayStation.html PlayStation}
875
- * Java interface.
876
- * @param {external:jQuery} [$div] - The jQuery DOM element where this Panel will deploy
877
- */
878
- constructor(act, ps, $div) {
879
- // ActivityPanel extends Container
880
- super();
881
- this.act = act;
882
- this.ps = ps;
883
- this.minimumSize = new Dimension(100, 100);
884
- this.preferredSize = new Dimension(500, 400);
885
- if ($div)
886
- this.$div = $div;
887
- else
888
- this.$div = $('<div/>', { class: 'JClicActivity', 'aria-label': getMsg('Activity panel') });
889
- this.act.initAutoContentProvider();
890
- }
891
-
892
- /**
893
- * Sets the size and position of this activity panel
894
- * @param {module:AWT.Rectangle} rect
895
- */
896
- setBounds(rect) {
897
- this.pos.x = rect.pos.x;
898
- this.pos.y = rect.pos.y;
899
- this.dim.width = rect.dim.width;
900
- this.dim.height = rect.dim.height;
901
-
902
- this.invalidate(rect);
903
- this.$div.css({
904
- position: 'relative',
905
- left: rect.pos.x,
906
- top: rect.pos.y,
907
- width: rect.dim.width,
908
- height: rect.dim.height
909
- });
910
- }
911
-
912
- /**
913
- * Prepares the visual components of the activity
914
- */
915
- buildVisualComponents() {
916
- this.playing = false;
917
- this.skin = null;
918
- if (this.act.skinFileName && this.act.skinFileName.length > 0 && this.act.skinFileName !== this.act.project.settings.skinFileName)
919
- this.skin = this.act.project.mediaBag.getSkinElement(this.act.skinFileName, this.ps);
920
-
921
- this.bgImage = null;
922
- if (this.act.bgImageFile && this.act.bgImageFile.length > 0) {
923
- const mbe = this.act.project.mediaBag.getElement(this.act.bgImageFile, true);
924
- if (mbe)
925
- this.bgImage = mbe.data;
926
- }
927
-
928
- this.backgroundColor = this.act.activityBgColor;
929
-
930
- if (this.act.transparentBg)
931
- this.backgroundTransparent = true;
932
-
933
- // TODO: fix bevel-border type
934
- if (this.act.border)
935
- this.border = true;
936
-
937
- const cssAct = {
938
- display: 'block',
939
- 'background-color': this.backgroundTransparent ? 'transparent' : this.backgroundColor
940
- };
941
-
942
- // Border shadow style Material Design, inspired in [http://codepen.io/Stenvh/pen/EaeWqW]
943
- if (this.border) {
944
- cssAct['box-shadow'] = '0 2px 5px 0 rgba(0, 0, 0, 0.16), 0 2px 10px 0 rgba(0, 0, 0, 0.12)';
945
- cssAct['border-radius'] = '2px';
946
- cssAct['color'] = '#272727';
947
- }
948
-
949
- if (this.act.activityBgGradient)
950
- cssAct['background-image'] = this.act.activityBgGradient.getCss();
951
-
952
- this.$div.css(cssAct);
953
- }
954
-
955
- /**
956
- * Activities should implement this method to update the graphic content of its panel. The method
957
- * will be called from {@link module:AWT.Container#update} when needed.
958
- * @param {module:AWT.Rectangle} dirtyRegion - Specifies the area to be updated. When `null`,
959
- * it's the whole panel.
960
- */
961
- updateContent(dirtyRegion) {
962
- // To be overridden by subclasses. Here does nothing.
963
- return super.updateContent(dirtyRegion);
964
- }
965
-
966
- /**
967
- * Plays the specified event sound
968
- * @param {string} event - The type of event to be performed
969
- */
970
- playEvent(event) {
971
- this.act.eventSounds.play(event);
972
- }
973
-
974
- /**
975
- * Basic initialization procedure, common to all activities.
976
- */
977
- initActivity() {
978
- if (this.playing) {
979
- this.playing = false;
980
- this.ps.reportEndActivity(this.act, this.solved);
981
- }
982
- this.solved = false;
983
- this.ps.reportNewActivity(this.act, 0);
984
- this.attachEvents();
985
- this.enableCounters();
986
- }
987
-
988
- /**
989
- * Called when the activity starts playing
990
- */
991
- startActivity() {
992
- this.playing = true;
993
- }
994
-
995
- /**
996
- * Called by {@link module:JClicPlayer.JClicPlayer JClicPlayer} when this activity panel is fully visible, just after the
997
- * initialization process.
998
- */
999
- activityReady() {
1000
- // To be overrided by subclasses
1001
- }
1002
-
1003
- /**
1004
- * Displays help about the activity
1005
- */
1006
- showHelp() {
1007
- // To be overrided by subclasses
1008
- }
1009
-
1010
- /**
1011
- * Sets the real dimension of this ActivityPanel.
1012
- * @param {module:AWT.Dimension} maxSize - The maximum surface available for the activity panel
1013
- * @returns {module:AWT.Dimension}
1014
- */
1015
- setDimension(maxSize) {
1016
- return new Dimension(
1017
- Math.min(maxSize.width, this.act.windowSize.width),
1018
- Math.min(maxSize.height, this.act.windowSize.height));
1019
- }
1020
-
1021
- /**
1022
- * Attaches the events specified in the `events` member to the `$div` member
1023
- */
1024
- attachEvents() {
1025
- this.events.forEach(ev => this.attachEvent(this.$div, ev));
1026
- // Prepare handler to check if we are in a touch device
1027
- if (!settings.TOUCH_DEVICE && $.inArray(TOUCH_TEST_EVENT, this.events) === -1)
1028
- this.attachEvent(this.$div, TOUCH_TEST_EVENT);
1029
- }
1030
-
1031
- /**
1032
- * Attaches a single event to the specified object
1033
- * @param {external:jQuery} $obj - The object to which the event will be attached
1034
- * @param {string} evt - The event name
1035
- */
1036
- attachEvent($obj, evt) {
1037
- $obj.on(evt, this, event => {
1038
- if (event.type === TOUCH_TEST_EVENT) {
1039
- if (!settings.TOUCH_DEVICE)
1040
- settings.TOUCH_DEVICE = true;
1041
- if ($.inArray(TOUCH_TEST_EVENT, this.events) === -1) {
1042
- // Disconnect handler
1043
- $obj.off(TOUCH_TEST_EVENT);
1044
- return;
1045
- }
1046
- }
1047
- return event.data.processEvent.call(event.data, event);
1048
- });
1049
- }
1050
-
1051
- /**
1052
- * Main handler used to process mouse, touch, keyboard and edit events.
1053
- * @param {external:Event} event - The HTML event to be processed
1054
- * @returns {boolean} - When this event handler returns `false`, jQuery will stop its
1055
- * propagation through the DOM tree. See: {@link http://api.jquery.com/on}
1056
- */
1057
- processEvent(_event) {
1058
- return false;
1059
- }
1060
-
1061
- /**
1062
- * Fits the panel within the `proposed` rectangle. The panel can occupy more space, but always
1063
- * not surpassing the `bounds` rectangle.
1064
- * @param {module:AWT.Rectangle} proposed - The proposed rectangle
1065
- * @param {module:AWT.Rectangle} bounds - The maximum allowed bounds
1066
- */
1067
- fitTo(proposed, bounds) {
1068
- const origin = new Point();
1069
- if (this.act.absolutePositioned && this.act.absolutePosition !== null) {
1070
- origin.x = Math.max(0, this.act.absolutePosition.x + proposed.pos.x);
1071
- origin.y = Math.max(0, this.act.absolutePosition.y + proposed.pos.y);
1072
- proposed.dim.width -= this.act.absolutePosition.x;
1073
- proposed.dim.height -= this.act.absolutePosition.y;
1074
- }
1075
- const d = this.setDimension(new Dimension(
1076
- Math.max(2 * this.act.margin + settings.MINIMUM_WIDTH, proposed.dim.width),
1077
- Math.max(2 * this.act.margin + settings.MINIMUM_HEIGHT, proposed.dim.height)));
1078
- if (!this.act.absolutePositioned) {
1079
- origin.moveTo(
1080
- Math.max(0, proposed.pos.x + (proposed.dim.width - d.width) / 2),
1081
- Math.max(0, proposed.pos.y + (proposed.dim.height - d.height) / 2));
1082
- }
1083
- if (origin.x + d.width > bounds.dim.width)
1084
- origin.x = Math.max(0, bounds.dim.width - d.width);
1085
- if (origin.y + d.height > bounds.dim.height)
1086
- origin.y = Math.max(0, bounds.dim.height - d.height);
1087
- this.setBounds(new Rectangle(origin.x, origin.y, d.width, d.height));
1088
-
1089
- // Build accessible components at the end of current tree
1090
- window.setTimeout(() => this.buildAccessibleComponents(), 0);
1091
- }
1092
-
1093
- /**
1094
- *
1095
- * Builds the accessible components needed for this ActivityPanel
1096
- * This method is called when all main elements are placed and visible, when the activity is ready
1097
- * to start or when resized.
1098
- */
1099
- buildAccessibleComponents() {
1100
- // Clear existing elements
1101
- if (this.accessibleCanvas && this.$canvas && this.$canvas.children().length > 0) {
1102
- // UPDATED May 2020: clearHitRegions has been deprecated!
1103
- // this.$canvas.get(-1).getContext('2d').clearHitRegions();
1104
- this.$canvas.empty();
1105
- }
1106
- // Create accessible elements in subclasses
1107
- }
1108
-
1109
- /**
1110
- * Forces the ending of the activity.
1111
- */
1112
- forceFinishActivity() {
1113
- // to be overrided by subclasses
1114
- }
1115
-
1116
- /**
1117
- * Ordinary ending of the activity, usually called form `processEvent`
1118
- * @param {boolean} result - `true` if the activity was successfully completed, `false` otherwise
1119
- */
1120
- finishActivity(result) {
1121
- this.playing = false;
1122
- this.solved = result;
1123
-
1124
- if (this.bc !== null)
1125
- this.bc.end();
1126
-
1127
- if (result) {
1128
- this.setAndPlayMsg('final', 'finishedOk');
1129
- } else {
1130
- this.setAndPlayMsg('finalError', 'finishedError');
1131
- }
1132
- this.ps.activityFinished(this.solved);
1133
- this.ps.reportEndActivity(this.act, this.solved);
1134
- }
1135
-
1136
- /**
1137
- * Sets the message to be displayed in the skin message box and optionally plays a sound event.
1138
- * @param {string} msgCode - Type of message (initial, final, finalError...)
1139
- * @param {string} [eventSoundsCode] - Optional name of the event sound to be played.
1140
- */
1141
- setAndPlayMsg(msgCode, eventSoundsCode) {
1142
- const msg = this.act.messages[msgCode] || null;
1143
- this.ps.setMsg(msg);
1144
- if (msg === null || msg.mediaContent === null)
1145
- this.playEvent(eventSoundsCode);
1146
- }
1147
-
1148
- /**
1149
- * Ends the activity
1150
- */
1151
- end() {
1152
- this.forceFinishActivity();
1153
- if (this.playing) {
1154
- if (this.bc !== null)
1155
- this.bc.end();
1156
- this.ps.reportEndActivity(this.act, this.solved);
1157
- this.playing = false;
1158
- this.solved = false;
1159
- }
1160
- this.clear();
1161
- }
1162
-
1163
- /**
1164
- * Miscellaneous cleaning operations
1165
- */
1166
- clear() {
1167
- // to be overridden by subclasses
1168
- }
1169
-
1170
- /**
1171
- * Enables or disables the three counters (time, score and actions)
1172
- * @param {boolean} eTime - Whether to enable or disable the time counter
1173
- * @param {boolean} eScore - Whether to enable or disable the score counter
1174
- * @param {boolean} eActions - Whether to enable or disable the actions counter
1175
- */
1176
- enableCounters(eTime, eScore, eActions) {
1177
- if (typeof eTime === 'undefined')
1178
- eTime = this.act.bTimeCounter;
1179
- if (typeof eScore === 'undefined')
1180
- eScore = this.act.bScoreCounter;
1181
- if (typeof eActions === 'undefined')
1182
- eActions = this.act.bActionsCounter;
1183
-
1184
- this.ps.setCounterEnabled('time', eTime);
1185
- if (this.act.countDownTime)
1186
- this.ps.setCountDown('time', this.act.maxTime);
1187
- this.ps.setCounterEnabled('score', eScore);
1188
- this.ps.setCounterEnabled('actions', eActions);
1189
- if (this.act.countDownActions)
1190
- this.ps.setCountDown('actions', this.act.maxActions);
1191
- }
1192
-
1193
- /**
1194
- * Shuffles the contents of the activity
1195
- * @param {module:boxes/ActiveBoxBag.ActiveBoxBag[]} bg - The sets of boxes to be shuffled
1196
- * @param {boolean} visible - The shuffle process must be animated on the screen (not yet implemented!)
1197
- * @param {boolean} fitInArea - Shuffled pieces cannot go out of the current area
1198
- */
1199
- shuffle(bg, visible, fitInArea) {
1200
- const steps = this.act.shuffles;
1201
- let i = steps;
1202
- while (i > 0) {
1203
- const k = i > steps ? steps : i;
1204
- bg.forEach(abb => { if (abb) abb.shuffleCells(k, fitInArea); });
1205
- i -= steps;
1206
- }
1207
- }
1208
- }
1209
-
1210
- Object.assign(ActivityPanel.prototype, {
1211
- /**
1212
- * The Activity this panel is related to
1213
- * @name module:Activity.ActivityPanel#act
1214
- * @type {module:Activity.Activity} */
1215
- act: null,
1216
- /**
1217
- * The jQuery div element used by this panel
1218
- * @name module:Activity.ActivityPanel#$div
1219
- * @type {external:jQuery} */
1220
- $div: null,
1221
- /**
1222
- * The jQuery main canvas element used by this panel
1223
- * @name module:Activity.ActivityPanel#$canvas
1224
- * @type {external:jQuery} */
1225
- $canvas: null,
1226
- /**
1227
- * Always true, since canvas hit regions have been deprecated!
1228
- * See: https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Hit_regions_and_accessibility
1229
- * @name module:Activity.ActivityPanel#accessibleCanvas
1230
- * @type {boolean}
1231
- */
1232
- accessibleCanvas: true,
1233
- /**
1234
- * The realized current {@link module:skins/Skin.Skin Skin}
1235
- * @name module:Activity.ActivityPanel#skin
1236
- * @type {module:skins/Skin.Skin} */
1237
- skin: null,
1238
- /**
1239
- * Background element (currently a `span`) used to place animated GIFs when needed
1240
- * @name module:Activity.ActivityPanel#$animatedBg
1241
- * @type {external:jQuery} */
1242
- $animatedBg: null,
1243
- /**
1244
- * Additional background element for animated GIFs, used in associations
1245
- * @name module:Activity.ActivityPanel#$animatedBgB
1246
- * @type {external:jQuery} */
1247
- $animatedBgB: null,
1248
- /**
1249
- * `true` when the activity is solved, `false` otherwise
1250
- * @name module:Activity.ActivityPanel#solved
1251
- * @type {boolean} */
1252
- solved: false,
1253
- /**
1254
- * The realized image used as a background
1255
- * @name module:Activity.ActivityPanel#bgImage
1256
- * @type {external:HTMLImageElement} */
1257
- bgImage: null,
1258
- /**
1259
- * `true` while the activity is playing
1260
- * @name module:Activity.ActivityPanel#playing
1261
- * @type {boolean} */
1262
- playing: false,
1263
- /**
1264
- * `true` if the activity is running for first time (not due to a click on the `replay` button)
1265
- * @name module:Activity.ActivityPanel#firstRun
1266
- * @type {boolean} */
1267
- firstRun: true,
1268
- /**
1269
- * Currently selected item. Used in some types of activities.
1270
- * @name module:Activity.ActivityPanel#currentItem
1271
- * @type {number} */
1272
- currentItem: 0,
1273
- /**
1274
- * The object used to connect cells and other elements in some types of activity
1275
- * @name module:Activity.ActivityPanel#bc
1276
- * @type {module:boxes/BoxConnector.BoxConnector} */
1277
- bc: null,
1278
- /**
1279
- * The PlayStation used to realize media objects and communicate with the player services
1280
- * (usually a {@link module:JClicPlayer.JClicPlayer JClicPlayer}
1281
- * @name module:Activity.ActivityPanel#ps
1282
- * @type {module:JClicPlayer.JClicPlayer} */
1283
- ps: null,
1284
- /**
1285
- * The minimum size of this kind of ActivityPanel
1286
- * @name module:Activity.ActivityPanel#minimumSize
1287
- * @type {module:AWT.Dimension} */
1288
- minimumSize: null,
1289
- /**
1290
- * The preferred size of this kind of ActivityPanel
1291
- * @name module:Activity.ActivityPanel#preferredSize
1292
- * @type {module:AWT.Dimension} */
1293
- preferredSize: null,
1294
- /**
1295
- * List of events intercepted by this ActivityPanel. Current events are: 'keydown', 'keyup',
1296
- * 'keypress', 'mousedown', 'mouseup', 'click', 'dblclick', 'mousemove', 'mouseenter',
1297
- * 'mouseleave', 'mouseover', 'mouseout', 'touchstart', 'touchend', 'touchmove' and 'touchcancel'.
1298
- * @name module:Activity.ActivityPanel#events
1299
- * @type {string[]} */
1300
- events: ['click'],
1301
- backgroundColor: null,
1302
- backgroundTransparent: false,
1303
- border: null,
1304
- });
1305
-
1306
- /**
1307
- * The panel class associated to each type of activity
1308
- * @type {module:Activity.ActivityPanel} */
1309
- Activity.Panel = ActivityPanel;
1310
-
1311
- export default Activity;