jclic 2.2.0 → 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 -664
  8. package/TRANSLATIONS.md +0 -11
  9. package/build-locales.mjs +0 -82
  10. package/dist/jclic-node.js +0 -31678
  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 -658
  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
@@ -1,426 +0,0 @@
1
- /**
2
- * File : activities/text/FillInBlanks.js
3
- * Created : 20/06/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 Catalan Educational Telematic Network (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
- import Activity from '../../Activity.js';
33
- import $ from 'jquery';
34
- import { fillString, setSelectionRange, getCaretCharacterOffsetWithin } from '../../Utils.js';
35
- import { TextActivityBase, TextActivityBasePanel } from './TextActivityBase.js';
36
-
37
- /**
38
- * In this type of activity the text document has some blanks that must be filled-in. The blanks
39
- * can be drop-down boxes or text fields (empty or pre-filled with an initial text). Blanks can
40
- * also have associated clues, shown as "pop-ups".
41
- * @extends module:activities/text/TextActivityBase.TextActivityBase
42
- */
43
- export class FillInBlanks extends TextActivityBase {
44
- /**
45
- * FillInBlanks constructor
46
- * @param {module:project/JClicProject.JClicProject} project - The {@link module:project/JClicProject.JClicProject JClicProject} to which this activity belongs
47
- */
48
- constructor(project) {
49
- super(project);
50
- }
51
-
52
- /**
53
- * This kind of activity usually makes use of the keyboard
54
- * @override
55
- * @returns {boolean}
56
- */
57
- needsKeyboard() {
58
- return true;
59
- }
60
- }
61
-
62
- Object.assign(FillInBlanks.prototype, {
63
- /**
64
- * Whether to jump or not to the next target when the current one is solved.
65
- * @name module:activities/text/FillInBlanks.FillInBlanks#autoJump
66
- * @type {boolean} */
67
- autoJump: false,
68
- /**
69
- * Whether to block or not the jump to other targets until the current one
70
- * is resolved.
71
- * @name module:activities/text/FillInBlanks.FillInBlanks#forceOkToAdvance
72
- * @type {boolean} */
73
- forceOkToAdvance: false,
74
- });
75
-
76
- /**
77
- * The {@link module:activities/text/TextActivityBase.TextActivityBasePanel} where {@link module:activities/text/FillInBlanks.FillInBlanks FillInBlanks} activities are played.
78
- * @extends module:activities/text/TextActivityBase.TextActivityBasePanel
79
- */
80
- export class FillInBlanksPanel extends TextActivityBasePanel {
81
- /**
82
- * FillInBlanksPanel constructor
83
- * @param {module:Activity.Activity} act - The {@link module:Activity.Activity Activity} to which this Panel belongs
84
- * @param {module:JClicPlayer.JClicPlayer} ps - Any object implementing the methods defined in the
85
- * [PlayStation](http://projectestac.github.io/jclic/apidoc/edu/xtec/jclic/PlayStation.html) Java interface.
86
- * @param {external:jQuery} [$div] - The jQuery DOM element where this Panel will deploy
87
- */
88
- constructor(act, ps, $div) {
89
- super(act, ps, $div);
90
- }
91
-
92
- /**
93
- * Creates a target DOM element for the provided target. This DOM element can be an editable
94
- * `span` or a `select` with specific `option` elements (when the target is a drop-down list)
95
- * @override
96
- * @param {module:activities/text/TextActivityDocument.TextTarget} target - The target related to the DOM object to be created
97
- * @param {external:jQuery} $span - - An initial DOM object (usually a `span`) that can be used
98
- * to store the target, or replaced by another type of object.
99
- * @returns {external:jQuery} - The jQuery DOM element loaded with the target data.
100
- */
101
- $createTargetElement(target, $span) {
102
-
103
- $span.addClass('JClicTextTarget');
104
-
105
- const idLabel = `target${`000${this.targets.length - 1}`.slice(-3)}`;
106
- if (target.isList && target.options && target.options.length > 0) {
107
- // Use a `select` element
108
- $span = $('<select/>', { id: idLabel, name: idLabel });
109
- if (target.options[0].trim() !== '')
110
- $('<option selected/>', { value: '', text: '' }).appendTo($span);
111
- target.options.forEach(op => $('<option/>', { value: op, text: op }).appendTo($span));
112
- target.$comboList = $span.on('focus change', event => {
113
- event.textTarget = target;
114
- this.processEvent(event);
115
- });
116
- } else {
117
- // Use a `span` element with the `contentEditable` attribute set `on`
118
- target.currentText = target.iniText ?
119
- target.iniText
120
- : fillString(target.iniChar, target.numIniChars);
121
-
122
- target.$span = $span.text(target.currentText).attr({
123
- contenteditable: 'true',
124
- id: idLabel,
125
- autocomplete: 'off',
126
- spellcheck: 'false'
127
- }).on('focus input blur', event => {
128
- event.textTarget = target;
129
- this.processEvent(event);
130
- }).on('keydown keyup', event => {
131
- // Catch `enter` key in Firefox
132
- if (event.keyCode === 13) {
133
- event.preventDefault();
134
- if (event.type === 'keydown') {
135
- // Simulate a `blur` event
136
- event.textTarget = target;
137
- event.type = 'blur';
138
- this.processEvent(event);
139
- }
140
- }
141
- });
142
- }
143
- return $span;
144
- }
145
-
146
- /**
147
- * Evaluates all the targets in this panel. This method is usually called from the `Check` button.
148
- * @override
149
- * @returns {boolean} - `true` when all targets are OK, `false` otherwise.
150
- */
151
- evaluatePanel() {
152
- let targetsOk = 0;
153
- const numTargets = this.targets.length;
154
- this.targets.forEach(target => {
155
- const
156
- result = this.act.ev.evalText(target.readCurrentText(), target.answers),
157
- ok = this.act.ev.isOk(result);
158
- target.targetStatus = ok ? 'SOLVED' : 'WITH_ERROR';
159
- if (ok)
160
- targetsOk++;
161
- this.markTarget(target, result);
162
- this.ps.reportNewAction(this.act, 'WRITE', target.currentText, target.getAnswers(), ok, targetsOk);
163
- });
164
- if (targetsOk === numTargets) {
165
- this.finishActivity(true);
166
- return true;
167
- } else
168
- this.playEvent('finishedError');
169
- return false;
170
- }
171
-
172
- /**
173
- * Checks if the specified TextTarget has a valid answer in its `currentText` field
174
- * @param {module:activities/text/TextActivityDocument.TextTarget} target - The target to check
175
- * @param {boolean} onlyCheck - When `true`, the cursor will no be re-positioned
176
- * @param {number} [jumpDirection] - `1` to go forward, `-1` to go back.
177
- * @returns {boolean} - `true` when the target contains a valid answer
178
- */
179
- checkTarget(target, onlyCheck, jumpDirection) {
180
- const
181
- result = this.act.ev.evalText(target.currentText, target.answers),
182
- ok = this.act.ev.isOk(result);
183
-
184
- target.targetStatus = ok ? 'SOLVED' : 'WITH_ERROR';
185
- if (onlyCheck)
186
- return ok;
187
-
188
- this.markTarget(target, result);
189
- const targetsOk = this.countSolvedTargets(false, false);
190
- if (target.currentText.length > 0)
191
- this.ps.reportNewAction(this.act, 'WRITE', target.currentText, target.getAnswers(), ok, targetsOk);
192
- if (ok && targetsOk === this.targets.length) {
193
- this.finishActivity(true);
194
- return ok;
195
- } else if (target.currentText.length > 0)
196
- this.playEvent(ok ? 'actionOk' : 'actionError');
197
-
198
- if (jumpDirection && jumpDirection !== 0) {
199
- let p = target.num + jumpDirection;
200
- if (p >= this.targets.length)
201
- p = 0;
202
- else if (p < 0)
203
- p = this.targets.length - 1;
204
-
205
- const destTarget = this.targets[p];
206
- if (destTarget.$span) {
207
- destTarget.$span.trigger('focus');
208
- setSelectionRange(destTarget.$span.get(-1), 0, 0);
209
- } else if (destTarget.$comboList)
210
- destTarget.$comboList.trigger('focus');
211
- }
212
- return ok;
213
- }
214
-
215
- /**
216
- * Counts the number of targets with `SOLVED` status
217
- * @param {boolean} checkNow - When `true`, all targets will be evaluated. Otherwise, only the
218
- * current value of `targetStatus` will be checked.
219
- * @param {boolean} [mark] - When `true`, errors in the target answer will be marked.
220
- * @returns {number} - The number of targets currently solved.
221
- */
222
- countSolvedTargets(checkNow, mark) {
223
- return this.targets.reduce((n, target) => {
224
- if (checkNow) {
225
- target.readCurrentText();
226
- this.checkTarget(target, !mark);
227
- }
228
- return target.targetStatus === 'SOLVED' ? ++n : n;
229
- }, 0);
230
- }
231
-
232
- /**
233
- * Visually marks the target as 'solved OK' or 'with errors'.
234
- * @param {module:activities/text/TextActivityDocument.TextTarget} target - The text target to be marked.
235
- * @param {number[]} attributes - - Array of flags indicating the status (OK or error) for each
236
- * character in `target.currentText`.
237
- */
238
- markTarget(target, attributes) {
239
- if (target.$comboList || this.act.ev.isOk(attributes))
240
- target.checkColors();
241
- else if (target.$span) {
242
- // Identify text fragments
243
- const
244
- txt = target.currentText,
245
- fragments = [];
246
- let
247
- currentStatus = -1,
248
- currentFragment = -1,
249
- i = 0;
250
- for (; i < attributes.length && i < txt.length; i++) {
251
- if (attributes[i] !== currentStatus) {
252
- fragments[++currentFragment] = '';
253
- currentStatus = attributes[i];
254
- }
255
- fragments[currentFragment] += txt.charAt(i);
256
- }
257
- if (i < txt.length)
258
- fragments[currentFragment] += txt.substring(i);
259
- // Empty and re-fill $span
260
- target.$span.empty();
261
- currentStatus = attributes[0];
262
- fragments.forEach(fragment => {
263
- $('<span/>')
264
- .text(fragment)
265
- .css(target.doc.style[currentStatus === 0 ? 'target' : 'targetError'].css)
266
- .appendTo(target.$span);
267
- currentStatus ^= 1;
268
- });
269
- }
270
- // Target has been marked, so clear the 'modified' flag
271
- target.flagModified = false;
272
- }
273
-
274
- /**
275
- * Called by {@link module:JClicPlayer.JClicPlayer JClicPlayer} when this activity panel is fully visible, just after the
276
- * initialization process.
277
- * @override
278
- */
279
- activityReady() {
280
- super.activityReady();
281
-
282
- // Prevent strange behavior with GoogleChrome when `white-space` CSS attribute is set to
283
- // `pre-wrap` (needed for tabulated texts)
284
- $('.JClicTextTarget').css('white-space', 'normal');
285
- if (this.targets.length > 0 && this.targets[0].$span)
286
- this.targets[0].$span.trigger('focus');
287
- }
288
-
289
- /**
290
- * Ordinary ending of the activity, usually called form `processEvent`
291
- * @override
292
- * @param {boolean} result - `true` if the activity was successfully completed, `false` otherwise
293
- */
294
- finishActivity(result) {
295
- this.targets.forEach(target => {
296
- if (target.$span)
297
- target.$span.removeAttr('contenteditable').trigger('blur');
298
- else if (target.$comboList)
299
- target.$comboList.prop('disabled', true).trigger('blur');
300
- });
301
- return super.finishActivity(result);
302
- }
303
-
304
- /**
305
- * Main handler used to process mouse, touch, keyboard and edit events.
306
- * @override
307
- * @param {external:Event} event - The HTML event to be processed
308
- * @returns {boolean} - When this event handler returns `false`, jQuery will stop its
309
- * propagation through the DOM tree. See: {@link http://api.jquery.com/on}
310
- */
311
- processEvent(event) {
312
- if (!super.processEvent(event))
313
- return false;
314
-
315
- const target = event.textTarget;
316
- let $span = null, pos = 0;
317
- switch (event.type) {
318
- case 'focus':
319
- if (target) {
320
- if (target.$span && target.$span.children().length > 0) {
321
- // Clear inner spans used to mark errors
322
- $span = target.$span;
323
- pos = Math.min(
324
- target.currentText.length,
325
- getCaretCharacterOffsetWithin($span.get(-1)));
326
- $span.empty();
327
- $span.text(target.currentText);
328
- setSelectionRange($span.get(-1), pos, pos);
329
- target.flagModified = true;
330
- } else if (target.$comboList)
331
- target.$comboList.css(target.doc.style['target'].css);
332
-
333
- if (target.$popup && (target.infoMode === 'always' || target.infoMode === 'onError' && target.targetStatus === 'WITH_ERROR'))
334
- this.showPopup(target.$popup, target.popupMaxTime, target.popupDelay);
335
- else
336
- this.showPopup(null);
337
- }
338
- break;
339
-
340
- case 'blur':
341
- if (target.flagModified && !this.$checkButton)
342
- this.checkTarget(target, false, 1);
343
- break;
344
-
345
- case 'input':
346
- if (target && target.$span) {
347
- $span = target.$span;
348
- let txt = $span.html();
349
- // Check for `enter` key
350
- if (/(<br>|\n|\r)/.test(txt)) {
351
- txt = txt.replace(/(<br>|\n|\r)/g, '');
352
- $span.html(txt);
353
- target.currentText = $span.text();
354
- return this.$checkButton ? false : this.checkTarget(target, false, 1);
355
- }
356
- // Check if text has changed
357
- // From here, use 'text' instead of 'html' to avoid HTML entities
358
- txt = $span.text();
359
- if (txt !== target.currentText) {
360
- // Span text has changed!
361
- target.flagModified = true;
362
- const added = txt.length - target.currentText.length;
363
- if (added > 0) {
364
- if (txt.indexOf(target.iniChar) >= 0) {
365
- // Remove filling chars
366
- pos = getCaretCharacterOffsetWithin($span.get(-1));
367
- for (let i = 0; i < added; i++) {
368
- const p = txt.indexOf(target.iniChar);
369
- if (p < 0)
370
- break;
371
- txt = txt.substring(0, p) + txt.substring(p + 1);
372
- if (p < pos)
373
- pos--;
374
- }
375
- $span.text(txt);
376
- setSelectionRange($span.get(-1), pos, pos);
377
- }
378
-
379
- // Check if current text exceeds max length
380
- if (txt.length > target.maxLenResp) {
381
- pos = getCaretCharacterOffsetWithin($span.get(-1));
382
- txt = txt.substring(0, target.maxLenResp);
383
- pos = Math.min(pos, txt.length);
384
- $span.text(txt);
385
- setSelectionRange($span.get(-1), pos, pos);
386
- }
387
- } else if (txt === '') {
388
- txt = target.iniChar;
389
- $span.text(txt);
390
- setSelectionRange($span.get(-1), 0, 0);
391
- }
392
- target.currentText = txt;
393
- }
394
- }
395
- break;
396
-
397
- case 'change':
398
- if (target && target.$comboList) {
399
- target.currentText = target.$comboList.val();
400
- target.flagModified = true;
401
- return this.$checkButton ? false : this.checkTarget(target, false, 1);
402
- }
403
- break;
404
-
405
- default:
406
- break;
407
- }
408
- return true;
409
- }
410
- }
411
-
412
- Object.assign(FillInBlanksPanel.prototype, {
413
- /**
414
- * Flag indicating if the activity is open or locked
415
- * @name module:activities/text/FillInBlanks.FillInBlanksPanel#locked
416
- * @type {boolean} */
417
- locked: true,
418
- });
419
-
420
- /**
421
- * Panel class associated to this type of activity: {@link module:activities/text/FillInBlanks.FillInBlanksPanel FillInBlanksPanel}
422
- * @type {class} */
423
- FillInBlanks.Panel = FillInBlanksPanel;
424
-
425
- // Register activity class
426
- export default Activity.registerClass('@text.FillInBlanks', FillInBlanks);
@@ -1,253 +0,0 @@
1
- /**
2
- * File : activities/text/Identify.js
3
- * Created : 20/06/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
- import Activity from '../../Activity.js';
33
- import { TextActivityBase, TextActivityBasePanel } from './TextActivityBase.js';
34
-
35
- /**
36
- * This type of text activity suggests users to click on specific words or single letters of a
37
- * given text, without any help on where these elements are placed.
38
- * @extends module:activities/text/TextActivityBase.TextActivityBase
39
- */
40
- export class IdentifyText extends TextActivityBase {
41
- /**
42
- * IdentifyText constructor
43
- * @param {module:project/JClicProject.JClicProject} project - The project to which this activity belongs
44
- */
45
- constructor(project) {
46
- super(project);
47
- }
48
- }
49
-
50
- /**
51
- * The {@link module:activities/text/TextActivityBase.TextActivityBasePanel TextActivityBasePanel} where {@link module:activities/text/IdentifyText.IdentifyText IdentifyText} activities are played.
52
- * @extends module:activities/text/TextActivityBase.TextActivityBasePanel
53
- */
54
- class IdentifyTextPanel extends TextActivityBasePanel {
55
- /**
56
- * IdentifyTextPanel constructor
57
- * @param {module:Activity.Activity} act - The {@link module:Activity.Activity Activity} to which this Panel belongs
58
- * @param {module:JClicPlayer.JClicPlayer} ps - Any object implementing the methods defined in the
59
- * [PlayStation](http://projectestac.github.io/jclic/apidoc/edu/xtec/jclic/PlayStation.html) Java interface.
60
- * @param {external:jQuery} [$div] - The jQuery DOM element where this Panel will deploy
61
- */
62
- constructor(act, ps, $div) {
63
- super(act, ps, $div);
64
- this.spanText = true;
65
- this.spanChars = act.type === 'identifyChars';
66
- this.spansChecked = new Set();
67
- }
68
-
69
- /**
70
- * Creates a target DOM element for the provided target.
71
- * @override
72
- * @param {module:activities/text/TextActivityDocument.TextTarget} target - The target related to the DOM object to be created
73
- * @param {external:jQuery} $span - - An initial DOM object (usually a `span`) that can be used
74
- * to store the target, or replaced by another type of object.
75
- * @returns {external:jQuery} - The jQuery DOM element loaded with the target data.
76
- */
77
- $createTargetElement(target, $span) {
78
- super.$createTargetElement(target, $span);
79
- const idLabel = `target${`000${this.targets.length - 1}`.slice(-3)}`;
80
- $span.on('click', event => {
81
- event.textTarget = target;
82
- event.idLabel = idLabel;
83
- this.processEvent(event);
84
- });
85
- return $span;
86
- }
87
-
88
- $createSpanElement($span) {
89
- $span.on('click', event => {
90
- event.$spanElement = $span;
91
- this.processEvent(event);
92
- });
93
- return $span;
94
- }
95
-
96
- /**
97
- * Basic initialization procedure
98
- * @override
99
- */
100
- initActivity() {
101
- super.initActivity(this);
102
- this.$div.find('.JClicTextDocument > p').css('cursor', 'pointer');
103
- this.$div.find('.JClicTextDocument > span').css('cursor', 'pointer');
104
- // Clean possible previous errors
105
- this.spansChecked.forEach($spanElement => $spanElement.css($spanElement.initialCSS || this.act.document.style['default'].css));
106
- this.spansChecked.clear();
107
- this.playing = true;
108
- }
109
-
110
- /**
111
- * Counts the number of targets that are solved
112
- * @returns {number}
113
- */
114
- countSolvedTargets() {
115
- return this.targets.filter(({ targetStatus }) => targetStatus === 'SOLVED').length;
116
- }
117
-
118
- /**
119
- * Evaluates all the targets in this panel. This method is usually called from the `Check` button.
120
- * @override
121
- * @returns {boolean} - `true` when all targets are OK, `false` otherwise.
122
- */
123
- evaluatePanel() {
124
- let targetsOk = 0;
125
- this.targets.forEach(target => {
126
- const ok = target.targetStatus === 'SOLVED';
127
- if (ok)
128
- targetsOk++;
129
- target.checkColors();
130
- this.ps.reportNewAction(this.act, 'SELECT', target.text, target.pos, ok, targetsOk);
131
- });
132
-
133
-
134
- if (targetsOk === this.targets.length && this.spansChecked.size === 0) {
135
- this.finishActivity(true);
136
- return true;
137
- } else {
138
- // Mark selected spans as error
139
- this.spansChecked.forEach($spanElement => $spanElement.css(this.act.document.style['targetError'].css));
140
- this.playEvent('finishedError');
141
- }
142
- return false;
143
- }
144
-
145
- /**
146
- * Ordinary ending of the activity, usually called form `processEvent`
147
- * @override
148
- * @param {boolean} result - `true` if the activity was successfully completed, `false` otherwise
149
- */
150
- finishActivity(result) {
151
- this.$div.find('.JClicTextDocument > p').css('cursor', 'pointer');
152
- return super.finishActivity(result);
153
- }
154
-
155
- /**
156
- * Main handler used to process mouse, touch, keyboard and edit events.
157
- * @override
158
- * @param {external:Event} event - The HTML event to be processed
159
- * @returns {boolean} - When this event handler returns `false`, jQuery will stop its
160
- * propagation through the DOM tree. See: {@link http://api.jquery.com/on}
161
- */
162
- processEvent(event) {
163
- if (!super.processEvent(event) ||
164
- event.timeStamp === this.lastTimeStamp)
165
- return false;
166
-
167
- if (event.timeStamp)
168
- this.lastTimeStamp = event.timeStamp;
169
-
170
- const target = event.textTarget;
171
- const $spanElement = event.$spanElement;
172
-
173
- switch (event.type) {
174
- case 'click':
175
- let text, pos, ok = false;
176
- if (target) {
177
- if (target.targetStatus === 'SOLVED')
178
- target.targetStatus = 'HIDDEN';
179
- else {
180
- target.targetStatus = 'SOLVED';
181
- ok = true;
182
- }
183
- text = target.text;
184
- pos = target.pos;
185
- // TODO: Just on/off target colors, don't mark it as error!
186
- target.checkColors();
187
- } else {
188
- if ($spanElement) {
189
- $spanElement.checked = !$spanElement.checked;
190
- if ($spanElement.checked) {
191
- this.spansChecked.add($spanElement);
192
- $spanElement.css(this.act.document.style.target.css);
193
- }
194
- else {
195
- this.spansChecked.delete($spanElement);
196
- $spanElement.css($spanElement.initialCSS || this.act.document.style.default.css);
197
- }
198
- text = $spanElement.text();
199
- }
200
- else
201
- text = 'unknown';
202
- pos = 0;
203
- }
204
-
205
- if (!this.$checkButton) {
206
- // Check and notify action
207
- const cellsAtPlace = this.countSolvedTargets();
208
- this.ps.reportNewAction(this.act, 'SELECT', text, pos, ok, cellsAtPlace);
209
-
210
- // End activity or play event sound
211
- if (ok && this.spansChecked.size === 0 && cellsAtPlace === this.targets.length)
212
- this.finishActivity(true);
213
- else
214
- this.playEvent(ok ? 'actionOk' : 'actionError');
215
- }
216
- event.preventDefault();
217
- break;
218
-
219
- default:
220
- break;
221
- }
222
- return true;
223
- }
224
- }
225
-
226
- Object.assign(IdentifyTextPanel.prototype, {
227
- /**
228
- * Flag indicating if targets must be visually marked when the activity begins. In this type of
229
- * activity should be always `false` to avoid revealing the words o letters that must be found.
230
- * @name module:activities/text/IdentifyText.IdentifyTextPanel#targetsMarked
231
- * @type {boolean} */
232
- targetsMarked: false,
233
- /**
234
- * Used to avoid duplicate event processing
235
- * @name module:activities/text/IdentifyText.IdentifyTextPanel#lastTimeStamp
236
- * @type {number}
237
- */
238
- lastTimeStamp: 0,
239
- /**
240
- * Set of non-target spans currently selected by the player.
241
- * This attribute should be empty to solve the activity.
242
- * @name module:activities/text/IdentifyText.IdentifyTextPanel#spansChecked
243
- * @type {set} */
244
- spansChecked: new Set(),
245
- });
246
-
247
- /**
248
- * Panel class associated to this type of activity: {@link module:activities/text/IdentifyText.IdentifyTextPanel IdentifyTextPanel}
249
- * @type {class} */
250
- IdentifyText.Panel = IdentifyTextPanel;
251
-
252
- // Register activity class
253
- export default Activity.registerClass('@text.Identify', IdentifyText);