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.
- package/README.md +5 -7
- package/dist-node/jclic-node.js +14157 -0
- package/dist-node/jclic-node.umd.cjs +530 -0
- package/package.json +38 -26
- package/.vscode/launch.json +0 -33
- package/.vscode/settings.json +0 -13
- package/CHANGELOG.md +0 -664
- package/TRANSLATIONS.md +0 -11
- package/build-locales.mjs +0 -82
- package/dist/jclic-node.js +0 -31678
- package/dist/jclic-node.js.map +0 -1
- package/dist/jclic.components.LICENSE +0 -2254
- package/dist/jclic.min.js +0 -27
- package/dist/jclic.min.js.map +0 -1
- package/eslint.config.mjs +0 -31
- package/jsdoc.config.js +0 -71
- package/locales/ar.po +0 -244
- package/locales/ast.po +0 -246
- package/locales/bs.po +0 -247
- package/locales/ca.po +0 -248
- package/locales/ca_ES@valencia.po +0 -248
- package/locales/cs.po +0 -244
- package/locales/da.po +0 -244
- package/locales/de.po +0 -246
- package/locales/el.po +0 -244
- package/locales/es.po +0 -248
- package/locales/eu.po +0 -244
- package/locales/fr.po +0 -244
- package/locales/gl.po +0 -244
- package/locales/he.po +0 -244
- package/locales/hr.po +0 -245
- package/locales/it.po +0 -246
- package/locales/ja.po +0 -242
- package/locales/jclic.js.pot +0 -241
- package/locales/nb_NO.po +0 -244
- package/locales/nl.po +0 -244
- package/locales/pl.po +0 -244
- package/locales/pt.po +0 -244
- package/locales/pt_BR.po +0 -248
- package/locales/ro.po +0 -248
- package/locales/ru.po +0 -245
- package/locales/ta.po +0 -244
- package/locales/tr.po +0 -246
- package/locales/uk.po +0 -247
- package/locales/vec.po +0 -244
- package/locales/zh_TW.po +0 -246
- package/patches/po2json+1.0.0-beta-3.patch +0 -12
- package/src/AWT.js +0 -2067
- package/src/Activity.js +0 -1311
- package/src/Deps.js +0 -232
- package/src/GlobalData.js +0 -5
- package/src/JClic.js +0 -196
- package/src/JClicPlayer.js +0 -1308
- package/src/PlayerHistory.js +0 -305
- package/src/Utils.js +0 -1355
- package/src/activities/associations/ComplexAssociation.js +0 -321
- package/src/activities/associations/SimpleAssociation.js +0 -519
- package/src/activities/memory/MemoryGame.js +0 -423
- package/src/activities/panels/Explore.js +0 -349
- package/src/activities/panels/Identify.js +0 -356
- package/src/activities/panels/InformationScreen.js +0 -262
- package/src/activities/panels/Menu.js +0 -209
- package/src/activities/panels/icons/ico00.png +0 -0
- package/src/activities/panels/icons/ico01.png +0 -0
- package/src/activities/panels/icons/ico02.png +0 -0
- package/src/activities/panels/icons/ico03.png +0 -0
- package/src/activities/panels/icons/icofolder.png +0 -0
- package/src/activities/puzzles/DoublePuzzle.js +0 -424
- package/src/activities/puzzles/ExchangePuzzle.js +0 -374
- package/src/activities/puzzles/HolePuzzle.js +0 -360
- package/src/activities/text/Complete.js +0 -127
- package/src/activities/text/Evaluator.js +0 -534
- package/src/activities/text/FillInBlanks.js +0 -426
- package/src/activities/text/IdentifyText.js +0 -253
- package/src/activities/text/OrderText.js +0 -421
- package/src/activities/text/TextActivityBase.js +0 -557
- package/src/activities/text/TextActivityDocument.js +0 -658
- package/src/activities/text/WrittenAnswer.js +0 -557
- package/src/activities/textGrid/CrossWord.js +0 -565
- package/src/activities/textGrid/WordSearch.js +0 -458
- package/src/activities/textGrid/icons/hIcon.svg +0 -3
- package/src/activities/textGrid/icons/vIcon.svg +0 -3
- package/src/automation/AutoContentProvider.js +0 -182
- package/src/automation/arith/Arith.js +0 -864
- package/src/bags/ActivitySequence.js +0 -318
- package/src/bags/ActivitySequenceElement.js +0 -161
- package/src/bags/ActivitySequenceJump.js +0 -140
- package/src/bags/ConditionalJumpInfo.js +0 -113
- package/src/bags/JumpInfo.js +0 -136
- package/src/bags/MediaBag.js +0 -215
- package/src/bags/MediaBagElement.js +0 -516
- package/src/boxes/AbstractBox.js +0 -699
- package/src/boxes/ActiveBagContent.js +0 -494
- package/src/boxes/ActiveBox.js +0 -810
- package/src/boxes/ActiveBoxBag.js +0 -357
- package/src/boxes/ActiveBoxContent.js +0 -484
- package/src/boxes/ActiveBoxGrid.js +0 -179
- package/src/boxes/BoxBag.js +0 -500
- package/src/boxes/BoxBase.js +0 -398
- package/src/boxes/BoxConnector.js +0 -325
- package/src/boxes/TextGrid.js +0 -887
- package/src/boxes/TextGridContent.js +0 -215
- package/src/init-jsdom.js +0 -65
- package/src/jclic-node.js +0 -219
- package/src/media/ActiveMediaBag.js +0 -145
- package/src/media/ActiveMediaPlayer.js +0 -297
- package/src/media/AudioBuffer.js +0 -219
- package/src/media/EventSounds.js +0 -169
- package/src/media/EventSoundsElement.js +0 -155
- package/src/media/MediaContent.js +0 -328
- package/src/media/MidiAudioPlayer.js +0 -254
- package/src/media/icons/audio.svg +0 -3
- package/src/media/icons/generic.svg +0 -3
- package/src/media/icons/mic.svg +0 -3
- package/src/media/icons/movie.svg +0 -3
- package/src/media/icons/music.svg +0 -3
- package/src/media/icons/url.svg +0 -3
- package/src/media/sounds/actionError.mp3 +0 -0
- package/src/media/sounds/actionOk.mp3 +0 -0
- package/src/media/sounds/click.mp3 +0 -0
- package/src/media/sounds/finishedError.mp3 +0 -0
- package/src/media/sounds/finishedOk.mp3 +0 -0
- package/src/media/sounds/start.mp3 +0 -0
- package/src/project/JClicProject.js +0 -282
- package/src/project/ProjectSettings.js +0 -273
- package/src/report/ActionReg.js +0 -123
- package/src/report/ActivityReg.js +0 -271
- package/src/report/EncryptMin.js +0 -210
- package/src/report/Reporter.js +0 -727
- package/src/report/SCORM.js +0 -272
- package/src/report/SequenceReg.js +0 -275
- package/src/report/SessionReg.js +0 -340
- package/src/report/SessionStorageReporter.js +0 -131
- package/src/report/TCPReporter.js +0 -628
- package/src/shapers/ClassicJigSaw.js +0 -138
- package/src/shapers/Holes.js +0 -77
- package/src/shapers/JigSaw.js +0 -161
- package/src/shapers/Rectangular.js +0 -78
- package/src/shapers/Shaper.js +0 -386
- package/src/shapers/TriangularJigSaw.js +0 -121
- package/src/skins/BlueSkin.js +0 -80
- package/src/skins/Counter.js +0 -152
- package/src/skins/CustomSkin.js +0 -412
- package/src/skins/DefaultSkin.js +0 -376
- package/src/skins/EmptySkin.js +0 -82
- package/src/skins/GreenSkin.js +0 -94
- package/src/skins/MiniSkin.js +0 -130
- package/src/skins/OrangeSkin.js +0 -78
- package/src/skins/SimpleSkin.js +0 -92
- package/src/skins/Skin.js +0 -1021
- package/src/skins/assets/actionsIcon.svg +0 -3
- package/src/skins/assets/appLogo.svg +0 -8
- package/src/skins/assets/basic.css +0 -41
- package/src/skins/assets/closeDialogIcon.svg +0 -3
- package/src/skins/assets/closeIcon.svg +0 -3
- package/src/skins/assets/copyIcon.svg +0 -3
- package/src/skins/assets/fullScreenExitIcon.svg +0 -3
- package/src/skins/assets/fullScreenIcon.svg +0 -3
- package/src/skins/assets/infoIcon.svg +0 -3
- package/src/skins/assets/main.css +0 -43
- package/src/skins/assets/mainHalf.css +0 -23
- package/src/skins/assets/mainTwoThirds.css +0 -23
- package/src/skins/assets/mini.css +0 -15
- package/src/skins/assets/nextIcon.svg +0 -3
- package/src/skins/assets/okDialogIcon.svg +0 -3
- package/src/skins/assets/prevIcon.svg +0 -3
- package/src/skins/assets/reports.css +0 -156
- package/src/skins/assets/reportsIcon.svg +0 -3
- package/src/skins/assets/scoreIcon.svg +0 -3
- package/src/skins/assets/simple.css +0 -16
- package/src/skins/assets/simpleHalf.css +0 -11
- package/src/skins/assets/simpleTwoThirds.css +0 -11
- package/src/skins/assets/timeIcon.svg +0 -4
- package/src/skins/assets/waitAnim.css +0 -54
- package/src/skins/assets/waitImgBig.svg +0 -3
- package/src/skins/assets/waitImgSmall.svg +0 -3
- package/webpack.config.mjs +0 -169
|
@@ -1,349 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* File : activities/panels/Explore.js
|
|
3
|
-
* Created : 04/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 $ from 'jquery';
|
|
33
|
-
import { Activity, ActivityPanel } from '../../Activity.js';
|
|
34
|
-
import ActiveBoxGrid from '../../boxes/ActiveBoxGrid.js';
|
|
35
|
-
import BoxBag from '../../boxes/BoxBag.js';
|
|
36
|
-
import { Rectangle, Point } from '../../AWT.js';
|
|
37
|
-
import Rectangular from '../../shapers/Rectangular.js';
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* This class of {@link module:Activity.Activity Activity} shows a panel with {@link module:boxes/ActiveBox.ActiveBox ActiveBox} objects. Users can click
|
|
41
|
-
* on this objects to obtain associated information. This associated information, displayed in
|
|
42
|
-
* a second panel, can be text graphics, sound, video... or a combination of them.
|
|
43
|
-
* @extends module:Activity.Activity
|
|
44
|
-
*/
|
|
45
|
-
export class Explore extends Activity {
|
|
46
|
-
/**
|
|
47
|
-
* Explore constructor
|
|
48
|
-
* @param {module:project/JClicProject.JClicProject} project - The {@link module:project/JClicProject.JClicProject JClicProject} to which this activity belongs
|
|
49
|
-
*/
|
|
50
|
-
constructor(project) {
|
|
51
|
-
super(project);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* Activities of this type never end, so automatic sequences must pause here
|
|
56
|
-
* @override
|
|
57
|
-
* @returns {boolean}
|
|
58
|
-
*/
|
|
59
|
-
mustPauseSequence() {
|
|
60
|
-
return true;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* Retrieves the minimum number of actions needed to solve this activity
|
|
65
|
-
* @override
|
|
66
|
-
* @returns {number}
|
|
67
|
-
*/
|
|
68
|
-
getMinNumActions() {
|
|
69
|
-
return 0;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
/**
|
|
73
|
-
* Usually this activity don't use random to shuffle internal components, but in some cases
|
|
74
|
-
* can make use of it.
|
|
75
|
-
* @override
|
|
76
|
-
* @returns {boolean}
|
|
77
|
-
*/
|
|
78
|
-
hasRandom() {
|
|
79
|
-
return true;
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* The {@link module:Activity.ActivityPanel ActivityPanel} where {@link module:activities/panels/Explore.Explore Explore} activities are played.
|
|
85
|
-
* @extends module:Activity.ActivityPanel
|
|
86
|
-
*/
|
|
87
|
-
export class ExplorePanel extends ActivityPanel {
|
|
88
|
-
/**
|
|
89
|
-
* ExplorePanel constructor
|
|
90
|
-
* @param {module:Activity.Activity} act - The {@link module:Activity.Activity Activity} to which this Panel belongs
|
|
91
|
-
* @param {module:JClicPlayer.JClicPlayer} ps - Any object implementing the methods defined in the
|
|
92
|
-
* [PlayStation](http://projectestac.github.io/jclic/apidoc/edu/xtec/jclic/PlayStation.html) Java interface.
|
|
93
|
-
* @param {external:jQuery} [$div] - The jQuery DOM element where this Panel will deploy
|
|
94
|
-
*/
|
|
95
|
-
constructor(act, ps, $div) {
|
|
96
|
-
super(act, ps, $div);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
/**
|
|
100
|
-
* Miscellaneous cleaning operations
|
|
101
|
-
* @override
|
|
102
|
-
*/
|
|
103
|
-
clear() {
|
|
104
|
-
if (this.bgA) {
|
|
105
|
-
this.bgA.end();
|
|
106
|
-
this.bgA = null;
|
|
107
|
-
}
|
|
108
|
-
if (this.bgB) {
|
|
109
|
-
this.bgB.end();
|
|
110
|
-
this.bgB = null;
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
/**
|
|
115
|
-
* Prepares the visual components of the activity
|
|
116
|
-
* @override
|
|
117
|
-
*/
|
|
118
|
-
buildVisualComponents() {
|
|
119
|
-
if (this.firstRun)
|
|
120
|
-
super.buildVisualComponents();
|
|
121
|
-
this.clear();
|
|
122
|
-
const
|
|
123
|
-
abcA = this.act.abc['primary'],
|
|
124
|
-
abcB = this.act.abc['secondary'];
|
|
125
|
-
|
|
126
|
-
if (abcA && abcB) {
|
|
127
|
-
if (abcA.image) {
|
|
128
|
-
abcA.setImgContent(this.act.project.mediaBag, null, false);
|
|
129
|
-
if (abcA.animatedGifFile && !abcA.shaper.rectangularShapes && !this.act.shuffleA)
|
|
130
|
-
this.$animatedBg = $('<span/>').css({
|
|
131
|
-
'background-image': `url(${abcA.animatedGifFile})`,
|
|
132
|
-
'background-position': 'center',
|
|
133
|
-
'background-repeat': 'no-repeat',
|
|
134
|
-
position: 'absolute'
|
|
135
|
-
}).appendTo(this.$div);
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
if (abcB.image)
|
|
139
|
-
abcB.setImgContent(this.act.project.mediaBag, null, false);
|
|
140
|
-
|
|
141
|
-
if (this.act.acp !== null)
|
|
142
|
-
this.act.acp.generateContent(abcA.nch, abcA.ncw, [abcA, abcB], false);
|
|
143
|
-
|
|
144
|
-
this.bgA = ActiveBoxGrid.createEmptyGrid(null, this, this.act.margin, this.act.margin, abcA);
|
|
145
|
-
const w = (this.act.boxGridPos === 'AUB' || this.act.boxGridPos === 'BUA') ? abcA.getTotalWidth() : abcB.w;
|
|
146
|
-
this.bgB = new ActiveBoxGrid(null, this, abcB.style, this.act.margin, this.act.margin, w, abcB.h, new Rectangular(1, 1));
|
|
147
|
-
|
|
148
|
-
this.bgA.setContent(abcA);
|
|
149
|
-
this.bgA.setDefaultIdAss();
|
|
150
|
-
if (this.$animatedBg)
|
|
151
|
-
this.bgA.setCellAttr('tmpTrans', true);
|
|
152
|
-
this.bgB.getActiveBox(0).setInactive(false);
|
|
153
|
-
this.bgA.setVisible(true);
|
|
154
|
-
this.bgB.setVisible(true);
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
/**
|
|
159
|
-
* Basic initialization procedure
|
|
160
|
-
* @override
|
|
161
|
-
*/
|
|
162
|
-
initActivity() {
|
|
163
|
-
super.initActivity();
|
|
164
|
-
if (!this.firstRun)
|
|
165
|
-
this.buildVisualComponents();
|
|
166
|
-
else
|
|
167
|
-
this.firstRun = false;
|
|
168
|
-
|
|
169
|
-
if (this.bgA && this.bgB) {
|
|
170
|
-
// Scramble cells
|
|
171
|
-
if (this.act.shuffleA)
|
|
172
|
-
this.shuffle([this.bgA], true, true);
|
|
173
|
-
|
|
174
|
-
if (this.useOrder)
|
|
175
|
-
this.currentItem = this.bgA.getNextItem(-1);
|
|
176
|
-
|
|
177
|
-
this.setAndPlayMsg('initial', 'start');
|
|
178
|
-
this.invalidate().update();
|
|
179
|
-
this.playing = true;
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
/**
|
|
184
|
-
* Updates the graphic content of this panel.
|
|
185
|
-
* This method will be called from {@link module:AWT.Container#update} when needed.
|
|
186
|
-
* @override
|
|
187
|
-
* @param {module:AWT.Rectangle} dirtyRegion - Specifies the area to be updated. When `null`,
|
|
188
|
-
* it's the whole panel.
|
|
189
|
-
*/
|
|
190
|
-
updateContent(dirtyRegion) {
|
|
191
|
-
super.updateContent(dirtyRegion);
|
|
192
|
-
if (this.bgA && this.bgB && this.$canvas) {
|
|
193
|
-
const
|
|
194
|
-
canvas = this.$canvas.get(-1),
|
|
195
|
-
ctx = canvas.getContext('2d');
|
|
196
|
-
if (!dirtyRegion)
|
|
197
|
-
dirtyRegion = new Rectangle(0, 0, canvas.width, canvas.height);
|
|
198
|
-
ctx.clearRect(dirtyRegion.pos.x, dirtyRegion.pos.y, dirtyRegion.dim.width, dirtyRegion.dim.height);
|
|
199
|
-
this.bgA.update(ctx, dirtyRegion);
|
|
200
|
-
this.bgB.update(ctx, dirtyRegion);
|
|
201
|
-
}
|
|
202
|
-
return this;
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
/**
|
|
206
|
-
* Sets the real dimension of this panel.
|
|
207
|
-
* @override
|
|
208
|
-
* @param {module:AWT.Dimension} preferredMaxSize - The maximum surface available for the activity panel
|
|
209
|
-
* @returns {module:AWT.Dimension}
|
|
210
|
-
*/
|
|
211
|
-
setDimension(preferredMaxSize) {
|
|
212
|
-
return !this.bgA || !this.bgB || this.getBounds().equals(preferredMaxSize) ?
|
|
213
|
-
preferredMaxSize :
|
|
214
|
-
BoxBag.layoutDouble(preferredMaxSize, this.bgA, this.bgB, this.act.boxGridPos, this.act.margin);
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
/**
|
|
218
|
-
* Sets the size and position of this activity panel
|
|
219
|
-
* @override
|
|
220
|
-
* @param {module:AWT.Rectangle} rect
|
|
221
|
-
*/
|
|
222
|
-
setBounds(rect) {
|
|
223
|
-
if (this.$canvas)
|
|
224
|
-
this.$canvas.remove();
|
|
225
|
-
super.setBounds(rect);
|
|
226
|
-
|
|
227
|
-
if (this.bgA || this.bgB) {
|
|
228
|
-
// Create the main canvas
|
|
229
|
-
this.$canvas = $(`<canvas width="${rect.dim.width}" height="${rect.dim.height}"/>`).css({
|
|
230
|
-
position: 'absolute',
|
|
231
|
-
top: 0,
|
|
232
|
-
left: 0
|
|
233
|
-
});
|
|
234
|
-
// Resize animated gif background
|
|
235
|
-
if (this.$animatedBg) {
|
|
236
|
-
const bgRect = this.bgA.getBounds();
|
|
237
|
-
this.$animatedBg.css({
|
|
238
|
-
left: bgRect.pos.x,
|
|
239
|
-
top: bgRect.pos.y,
|
|
240
|
-
width: `${bgRect.dim.width}px`,
|
|
241
|
-
height: `${bgRect.dim.height}px`,
|
|
242
|
-
'background-size': `${bgRect.dim.width}px ${bgRect.dim.height}px`
|
|
243
|
-
});
|
|
244
|
-
}
|
|
245
|
-
this.$div.append(this.$canvas);
|
|
246
|
-
// Repaint all
|
|
247
|
-
this.invalidate().update();
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
/**
|
|
252
|
-
* Builds the accessible components needed for this ActivityPanel
|
|
253
|
-
* This method is called when all main elements are placed and visible, when the activity is ready
|
|
254
|
-
* to start or when resized.
|
|
255
|
-
* @override
|
|
256
|
-
*/
|
|
257
|
-
buildAccessibleComponents() {
|
|
258
|
-
if (this.$canvas && this.accessibleCanvas) {
|
|
259
|
-
super.buildAccessibleComponents();
|
|
260
|
-
if (this.bgA)
|
|
261
|
-
this.bgA.buildAccessibleElements(this.$canvas, this.$div);
|
|
262
|
-
if (this.bgB)
|
|
263
|
-
this.bgB.buildAccessibleElements(this.$canvas, this.$div);
|
|
264
|
-
}
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
/**
|
|
268
|
-
* Main handler used to process mouse, touch, keyboard and edit events
|
|
269
|
-
* @override
|
|
270
|
-
* @param {external:Event} event - The HTML event to be processed
|
|
271
|
-
* @returns {boolean} - When this event handler returns `false`, jQuery will stop its
|
|
272
|
-
* propagation through the DOM tree. See: {@link http://api.jquery.com/on}
|
|
273
|
-
*/
|
|
274
|
-
processEvent(event) {
|
|
275
|
-
if (this.playing) {
|
|
276
|
-
const p = new Point(
|
|
277
|
-
event.pageX - this.$div.offset().left,
|
|
278
|
-
event.pageY - this.$div.offset().top),
|
|
279
|
-
// Array to be filled with actions to be executed at the end of event processing
|
|
280
|
-
delayedActions = [];
|
|
281
|
-
|
|
282
|
-
switch (event.type) {
|
|
283
|
-
case 'click':
|
|
284
|
-
this.ps.stopMedia(1);
|
|
285
|
-
const bx1 = this.bgA.findActiveBox(p);
|
|
286
|
-
if (bx1) {
|
|
287
|
-
const bx2 = this.bgB.getActiveBox(0);
|
|
288
|
-
if (bx1.idAss !== -1 && (!this.act.useOrder || bx1.idOrder === this.currentItem)) {
|
|
289
|
-
bx2.setContent(this.act.abc['secondary'], bx1.idAss);
|
|
290
|
-
if (!bx2.playMedia(this.ps, delayedActions) && !bx1.playMedia(this.ps, delayedActions))
|
|
291
|
-
this.playEvent('CLICK');
|
|
292
|
-
if (this.act.useOrder)
|
|
293
|
-
this.currentItem = this.bgA.getNextItem(this.currentItem);
|
|
294
|
-
this.ps.reportNewAction(this.act, 'SELECT', bx1.getDescription(), bx2.getDescription(), true, 0);
|
|
295
|
-
// Modified May 2020: Focusing `accessibleElement` will always draw a border on bx2
|
|
296
|
-
// if (bx2.$accessibleElement)
|
|
297
|
-
// bx2.$accessibleElement.focus();
|
|
298
|
-
|
|
299
|
-
// Clic 3.0 behavior, applied only to one-cell activities:
|
|
300
|
-
if (bx1.idAss === 0 && this.bgA.getNumCells() === 1) {
|
|
301
|
-
const seq = this.act.project.activitySequence;
|
|
302
|
-
const ase = seq.getCurrentAct();
|
|
303
|
-
if (ase && seq.hasNextAct(true) && ase.delay > 0
|
|
304
|
-
&& (seq.getNavButtonsFlag() !== 'both' && seq.getNavButtonsFlag() !== 'fwd')) {
|
|
305
|
-
this.finishActivity(true);
|
|
306
|
-
}
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
} else {
|
|
310
|
-
bx2.clear();
|
|
311
|
-
bx2.setInactive(false);
|
|
312
|
-
}
|
|
313
|
-
this.update();
|
|
314
|
-
}
|
|
315
|
-
break;
|
|
316
|
-
}
|
|
317
|
-
delayedActions.forEach(action => action());
|
|
318
|
-
event.preventDefault();
|
|
319
|
-
}
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
Object.assign(ExplorePanel.prototype, {
|
|
324
|
-
/**
|
|
325
|
-
* The {@link module:boxes/ActiveBoxbag.ActiveBoxBag ActiveBoxBag} object containing the information to be displayed in the `primary` panel
|
|
326
|
-
* @name module:activities/panels/Explore.ExplorePanel#bgA
|
|
327
|
-
* @type {module:boxes/ActiveBoxBag.ActiveBoxBag} */
|
|
328
|
-
bgA: null,
|
|
329
|
-
/**
|
|
330
|
-
* The {@link module:boxes/ActiveBoxbag.ActiveBoxBag ActiveBoxBag} object containing the information associated to `primary` elements.
|
|
331
|
-
* Only one of this elements will be showed for each click done in the `primary` panel.
|
|
332
|
-
* @name module:activities/panels/Explore.ExplorePanel#bgB
|
|
333
|
-
* @type {module:boxes/ActiveBoxBag.ActiveBoxBag} */
|
|
334
|
-
bgB: null,
|
|
335
|
-
/**
|
|
336
|
-
* List of mouse, touch and keyboard events intercepted by this panel
|
|
337
|
-
* @override
|
|
338
|
-
* @name module:activities/panels/Explore.ExplorePanel#events
|
|
339
|
-
* @type {string[]} */
|
|
340
|
-
events: ['click'],
|
|
341
|
-
});
|
|
342
|
-
|
|
343
|
-
/**
|
|
344
|
-
* Panel class associated to this type of activity: {@link module:activities/panels/Explore.ExplorePanel ExplorePanel}
|
|
345
|
-
* @type {class} */
|
|
346
|
-
Explore.Panel = ExplorePanel;
|
|
347
|
-
|
|
348
|
-
// Register activity class
|
|
349
|
-
export default Activity.registerClass('@panels.Explore', Explore);
|
|
@@ -1,356 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* File : activities/panels/Identify.js
|
|
3
|
-
* Created : 03/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
|
-
/* global window */
|
|
33
|
-
|
|
34
|
-
import $ from 'jquery';
|
|
35
|
-
import { Activity, ActivityPanel } from '../../Activity.js';
|
|
36
|
-
import ActiveBoxGrid from '../../boxes/ActiveBoxGrid.js';
|
|
37
|
-
import BoxBag from '../../boxes/BoxBag.js';
|
|
38
|
-
import { Rectangle, Point } from '../../AWT.js';
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* The aim of this type of {@link module:Activity.Activity Activity} is to identify {@link module:boxes/ActiveBox.ActiveBox ActiveBox} elements in a panel
|
|
42
|
-
* that satisfy a specific condition, usually exposed in the main message.
|
|
43
|
-
* @extends module:Activity.Activity
|
|
44
|
-
*/
|
|
45
|
-
export class Identify extends Activity {
|
|
46
|
-
/**
|
|
47
|
-
* Identify constructor
|
|
48
|
-
* @param {module:project/JClicProject.JClicProject} project - The {@link module:project/JClicProject.JClicProject JClicProject} to which this activity belongs
|
|
49
|
-
*/
|
|
50
|
-
constructor(project) {
|
|
51
|
-
super(project);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* Retrieves the minimum number of actions needed to solve this activity
|
|
56
|
-
* @override
|
|
57
|
-
* @returns {number}
|
|
58
|
-
*/
|
|
59
|
-
getMinNumActions() {
|
|
60
|
-
return this.cellsToMatch;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* Whether or not the activity uses random to shuffle internal components
|
|
65
|
-
* @override
|
|
66
|
-
* @returns {boolean}
|
|
67
|
-
*/
|
|
68
|
-
hasRandom() {
|
|
69
|
-
return true;
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
Object.assign(Identify.prototype, {
|
|
74
|
-
/**
|
|
75
|
-
* Number of not assigned cells (calculated in {@link module:activities/panels/Identify.IdentifyPanel#buildVisualComponents buildVisualComponents})
|
|
76
|
-
* @name module:activities/panels/Identify.Identify#nonAssignedCells
|
|
77
|
-
* @type {number} */
|
|
78
|
-
nonAssignedCells: 0,
|
|
79
|
-
/**
|
|
80
|
-
* Number of cells the user must identify to complete the activity (calculated in
|
|
81
|
-
* {@link module:activities/panels/Identify.IdentifyPanel#buildVisualComponents buildVisualComponents})
|
|
82
|
-
* @name module:activities/panels/Identify.Identify#cellsToMatch
|
|
83
|
-
* @type {number} */
|
|
84
|
-
cellsToMatch: 1,
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* The {@link module:Activity.ActivityPanel ActivityPanel} where {@link module:activities/panels/Identify.Identify Identify} activities are played.
|
|
89
|
-
* @extends module:Activity.ActivityPanel
|
|
90
|
-
*/
|
|
91
|
-
export class IdentifyPanel extends ActivityPanel {
|
|
92
|
-
/**
|
|
93
|
-
* IdentifyPanel constructor
|
|
94
|
-
* @param {module:Activity.Activity} act - The {@link module:Activity.Activity Activity} to which this Panel belongs
|
|
95
|
-
* @param {module:JClicPlayer.JClicPlayer} ps - Any object implementing the methods defined in the
|
|
96
|
-
* [PlayStation](http://projectestac.github.io/jclic/apidoc/edu/xtec/jclic/PlayStation.html) Java interface.
|
|
97
|
-
* @param {external:jQuery} [$div] - The jQuery DOM element where this Panel will deploy
|
|
98
|
-
*/
|
|
99
|
-
constructor(act, ps, $div) {
|
|
100
|
-
super(act, ps, $div);
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
/**
|
|
104
|
-
* Miscellaneous cleaning operations
|
|
105
|
-
* @override
|
|
106
|
-
*/
|
|
107
|
-
clear() {
|
|
108
|
-
if (this.bg) {
|
|
109
|
-
this.bg.end();
|
|
110
|
-
this.bg = null;
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
/**
|
|
115
|
-
* Prepares the visual components of the activity
|
|
116
|
-
* @override
|
|
117
|
-
*/
|
|
118
|
-
buildVisualComponents() {
|
|
119
|
-
if (this.firstRun)
|
|
120
|
-
super.buildVisualComponents();
|
|
121
|
-
this.clear();
|
|
122
|
-
const
|
|
123
|
-
abc = this.act.abc['primary'],
|
|
124
|
-
solved = this.act.abc['solvedPrimary'];
|
|
125
|
-
if (abc) {
|
|
126
|
-
if (abc.image) {
|
|
127
|
-
abc.setImgContent(this.act.project.mediaBag, null, false);
|
|
128
|
-
if (abc.animatedGifFile && !abc.shaper.rectangularShapes && !this.act.shuffleA)
|
|
129
|
-
this.$animatedBg = $('<span/>').css({
|
|
130
|
-
'background-image': `url(${abc.animatedGifFile})`,
|
|
131
|
-
'background-position': 'center',
|
|
132
|
-
'background-repeat': 'no-repeat',
|
|
133
|
-
position: 'absolute'
|
|
134
|
-
}).appendTo(this.$div);
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
if (solved && solved.image)
|
|
138
|
-
solved.setImgContent(this.act.project.mediaBag, null, false);
|
|
139
|
-
|
|
140
|
-
if (this.act.acp !== null) {
|
|
141
|
-
const contentKit = [abc];
|
|
142
|
-
if (solved) {
|
|
143
|
-
contentKit.push(null);
|
|
144
|
-
contentKit.push(solved);
|
|
145
|
-
}
|
|
146
|
-
this.act.acp.generateContent(abc.nch, abc.ncw, contentKit, false);
|
|
147
|
-
}
|
|
148
|
-
this.bg = ActiveBoxGrid.createEmptyGrid(null, this,
|
|
149
|
-
this.act.margin, this.act.margin,
|
|
150
|
-
abc);
|
|
151
|
-
this.bg.setContent(abc, solved || null);
|
|
152
|
-
this.bg.setAlternative(false);
|
|
153
|
-
if (this.$animatedBg)
|
|
154
|
-
this.bg.setCellAttr('tmpTrans', true);
|
|
155
|
-
this.bg.setDefaultIdAss();
|
|
156
|
-
this.act.nonAssignedCells = 0;
|
|
157
|
-
this.act.cellsToMatch = 0;
|
|
158
|
-
const n = this.bg.getNumCells();
|
|
159
|
-
for (let i = 0; i < n; i++) {
|
|
160
|
-
const
|
|
161
|
-
bx = this.bg.getActiveBox(i),
|
|
162
|
-
id = bx.idAss;
|
|
163
|
-
if (id === 1)
|
|
164
|
-
this.act.cellsToMatch++;
|
|
165
|
-
else if (id === -1) {
|
|
166
|
-
this.act.nonAssignedCells++;
|
|
167
|
-
bx.switchToAlt(this.ps);
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
this.bg.setVisible(true);
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
/**
|
|
175
|
-
* Basic initialization procedure
|
|
176
|
-
* @override
|
|
177
|
-
*/
|
|
178
|
-
initActivity() {
|
|
179
|
-
super.initActivity();
|
|
180
|
-
if (!this.firstRun)
|
|
181
|
-
this.buildVisualComponents();
|
|
182
|
-
else
|
|
183
|
-
this.firstRun = false;
|
|
184
|
-
|
|
185
|
-
if (this.bg) {
|
|
186
|
-
if (this.act.shuffleA)
|
|
187
|
-
this.shuffle([this.bg], true, true);
|
|
188
|
-
|
|
189
|
-
if (this.useOrder)
|
|
190
|
-
this.currentItem = this.bg.getNextItem(-1);
|
|
191
|
-
|
|
192
|
-
this.setAndPlayMsg('initial', 'start');
|
|
193
|
-
this.invalidate().update();
|
|
194
|
-
this.playing = true;
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
/**
|
|
199
|
-
* Updates the graphic content of this panel.
|
|
200
|
-
* This method will be called from {@link module:AWT.Container#update} when needed.
|
|
201
|
-
* @override
|
|
202
|
-
* @param {module:AWT.Rectangle} dirtyRegion - Specifies the area to be updated. When `null`,
|
|
203
|
-
* it's the whole panel.
|
|
204
|
-
*/
|
|
205
|
-
updateContent(dirtyRegion) {
|
|
206
|
-
super.updateContent(dirtyRegion);
|
|
207
|
-
|
|
208
|
-
if (this.bg && this.$canvas) {
|
|
209
|
-
const
|
|
210
|
-
canvas = this.$canvas.get(-1),
|
|
211
|
-
ctx = canvas.getContext('2d');
|
|
212
|
-
if (!dirtyRegion)
|
|
213
|
-
dirtyRegion = new Rectangle(0, 0, canvas.width, canvas.height);
|
|
214
|
-
ctx.clearRect(dirtyRegion.pos.x, dirtyRegion.pos.y, dirtyRegion.dim.width, dirtyRegion.dim.height);
|
|
215
|
-
this.bg.update(ctx, dirtyRegion);
|
|
216
|
-
}
|
|
217
|
-
return super.updateContent(dirtyRegion);
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
/**
|
|
221
|
-
* Sets the real dimension of this panel.
|
|
222
|
-
* @override
|
|
223
|
-
* @param {module:AWT.Dimension} preferredMaxSize - The maximum surface available for the activity panel
|
|
224
|
-
* @returns {module:AWT.Dimension}
|
|
225
|
-
*/
|
|
226
|
-
setDimension(preferredMaxSize) {
|
|
227
|
-
return this.getBounds().equals(preferredMaxSize) ?
|
|
228
|
-
preferredMaxSize :
|
|
229
|
-
BoxBag.layoutSingle(preferredMaxSize, this.bg, this.act.margin);
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
/**
|
|
233
|
-
* Sets the size and position of this activity panel
|
|
234
|
-
* @override
|
|
235
|
-
* @param {module:AWT.Rectangle} rect
|
|
236
|
-
*/
|
|
237
|
-
setBounds(rect) {
|
|
238
|
-
if (this.$canvas)
|
|
239
|
-
this.$canvas.remove();
|
|
240
|
-
|
|
241
|
-
super.setBounds(rect);
|
|
242
|
-
if (this.bg) {
|
|
243
|
-
this.$canvas = $(`<canvas width="${rect.dim.width}" height="${rect.dim.height}"/>`).css({
|
|
244
|
-
position: 'absolute',
|
|
245
|
-
top: 0,
|
|
246
|
-
left: 0
|
|
247
|
-
});
|
|
248
|
-
// Resize animated gif background
|
|
249
|
-
if (this.$animatedBg) {
|
|
250
|
-
const bgRect = this.bg.getBounds();
|
|
251
|
-
this.$animatedBg.css({
|
|
252
|
-
left: bgRect.pos.x,
|
|
253
|
-
top: bgRect.pos.y,
|
|
254
|
-
width: `${bgRect.dim.width}px`,
|
|
255
|
-
height: `${bgRect.dim.height}px`,
|
|
256
|
-
'background-size': `${bgRect.dim.width}px ${bgRect.dim.height}px`
|
|
257
|
-
});
|
|
258
|
-
}
|
|
259
|
-
this.$div.append(this.$canvas);
|
|
260
|
-
this.invalidate().update();
|
|
261
|
-
window.setTimeout(() => this.bg ? this.bg.buildAccessibleElements(this.$canvas, this.$div) : null, 0);
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
/**
|
|
266
|
-
* Builds the accessible components needed for this ActivityPanel
|
|
267
|
-
* This method is called when all main elements are placed and visible, when the activity is ready
|
|
268
|
-
* to start or when resized.
|
|
269
|
-
* @override
|
|
270
|
-
*/
|
|
271
|
-
buildAccessibleComponents() {
|
|
272
|
-
if (this.bg && this.$canvas && this.accessibleCanvas) {
|
|
273
|
-
super.buildAccessibleComponents();
|
|
274
|
-
this.bg.buildAccessibleElements(this.$canvas, this.$div);
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
/**
|
|
279
|
-
* Main handler used to process mouse, touch, keyboard and edit events
|
|
280
|
-
* @override
|
|
281
|
-
* @param {external:Event} event - The HTML event to be processed
|
|
282
|
-
* @returns {boolean} - When this event handler returns `false`, jQuery will stop its
|
|
283
|
-
* propagation through the DOM tree. See: {@link http://api.jquery.com/on}
|
|
284
|
-
*/
|
|
285
|
-
processEvent(event) {
|
|
286
|
-
if (this.playing) {
|
|
287
|
-
const p = new Point(
|
|
288
|
-
event.pageX - this.$div.offset().left,
|
|
289
|
-
event.pageY - this.$div.offset().top);
|
|
290
|
-
// Flag for assuring that only one media plays per event (avoid event sounds overlapping
|
|
291
|
-
// cell's media sounds)
|
|
292
|
-
let m = false;
|
|
293
|
-
// Array to be filled with actions to be executed at the end of event processing
|
|
294
|
-
const delayedActions = [];
|
|
295
|
-
|
|
296
|
-
switch (event.type) {
|
|
297
|
-
case 'click':
|
|
298
|
-
this.ps.stopMedia(1);
|
|
299
|
-
// Find the box behind the clicked point
|
|
300
|
-
const bx = this.bg ? this.bg.findActiveBox(p) : null;
|
|
301
|
-
if (bx) {
|
|
302
|
-
if (bx.idAss !== -1) {
|
|
303
|
-
// Check if it's a valid move
|
|
304
|
-
let ok = false;
|
|
305
|
-
const src = bx.getDescription();
|
|
306
|
-
m = m || bx.playMedia(this.ps, delayedActions);
|
|
307
|
-
if (bx.idAss === 1 && (!this.act.useOrder || bx.idOrder === this.currentItem)) {
|
|
308
|
-
ok = true;
|
|
309
|
-
bx.idAss = -1;
|
|
310
|
-
if (bx.switchToAlt(this.ps))
|
|
311
|
-
m = m || bx.playMedia(this.ps, delayedActions);
|
|
312
|
-
else
|
|
313
|
-
bx.clear();
|
|
314
|
-
if (this.act.useOrder)
|
|
315
|
-
this.currentItem = this.bg.getNextItem(this.currentItem, 1);
|
|
316
|
-
}
|
|
317
|
-
const cellsOk = this.bg.countCellsWithIdAss(-1);
|
|
318
|
-
this.ps.reportNewAction(this.act, 'SELECT', src, null, ok, cellsOk - this.act.nonAssignedCells);
|
|
319
|
-
if (ok && cellsOk === this.act.cellsToMatch + this.act.nonAssignedCells)
|
|
320
|
-
this.finishActivity(true);
|
|
321
|
-
else if (!m)
|
|
322
|
-
this.playEvent(ok ? 'actionOk' : 'actionError');
|
|
323
|
-
this.update();
|
|
324
|
-
} else {
|
|
325
|
-
this.playEvent('actionError');
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
break;
|
|
329
|
-
}
|
|
330
|
-
delayedActions.forEach(action => action());
|
|
331
|
-
event.preventDefault();
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
Object.assign(IdentifyPanel.prototype, {
|
|
337
|
-
/**
|
|
338
|
-
* The {@link module:boxes/ActiveBoxbag.ActiveBoxBag ActiveBoxBag} containing the information to be displayed on the panel.
|
|
339
|
-
* @name module:activities/panels/Identify.IdentifyPanel#bg
|
|
340
|
-
* @type {module:boxes/ActiveBoxBag.ActiveBoxBag} */
|
|
341
|
-
bg: null,
|
|
342
|
-
/**
|
|
343
|
-
* List of mouse, touch and keyboard events intercepted by this panel
|
|
344
|
-
* @override
|
|
345
|
-
* @name module:activities/panels/Identify.IdentifyPanel#events
|
|
346
|
-
* @type {string[]} */
|
|
347
|
-
events: ['click'],
|
|
348
|
-
});
|
|
349
|
-
|
|
350
|
-
/**
|
|
351
|
-
* Panel class associated to this type of activity: {@link module:activities/panels/Identify.IdentifyPanel IdentifyPanel}
|
|
352
|
-
* @type {class} */
|
|
353
|
-
Identify.Panel = IdentifyPanel;
|
|
354
|
-
|
|
355
|
-
// Register activity class
|
|
356
|
-
export default Activity.registerClass('@panels.Identify', Identify);
|