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,297 +0,0 @@
1
- /**
2
- * File : media/ActiveMediaPlayer.js
3
- * Created : 28/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 navigator */
33
-
34
- import $ from 'jquery';
35
- import AudioBuffer from './AudioBuffer.js';
36
-
37
- /**
38
- * This kind of object encapsulates a realized {@link module:media/MediaContent.MediaContent} and provides methods to start,
39
- * stop, pause and record different types of media (audio, video, MIDI, voice recording...)
40
- */
41
- export class ActiveMediaPlayer {
42
- /**
43
- * ActiveMediaPlayer constructor
44
- * @param {module:media/MediaContent.MediaContent} mc - - The content used by this player
45
- * @param {module:bags/MediaBag.MediaBag} mb - The project's MediaBag
46
- * @param {module:JClicPlayer.JClicPlayer} ps - An object implementing the
47
- * {@link http://projectestac.github.io/jclic/apidoc/edu/xtec/jclic/PlayStation.html PlayStation} interface,
48
- * usually a {@link module:JClicPlayer.JClicPlayer JClicPlayer}.
49
- */
50
- constructor(mc, mb, ps) {
51
- this.mc = mc;
52
- this.ps = ps;
53
- switch (mc.type) {
54
- case 'RECORD_AUDIO':
55
- if (ActiveMediaPlayer.AUDIO_BUFFERS) {
56
- this.clearAudioBuffer(mc.recBuffer);
57
- ActiveMediaPlayer.AUDIO_BUFFERS[mc.recBuffer] = new AudioBuffer(mc.length);
58
- }
59
- /* falls through */
60
- case 'PLAY_RECORDED_AUDIO':
61
- this.useAudioBuffer = true;
62
- break;
63
- case 'PLAY_AUDIO':
64
- case 'PLAY_VIDEO':
65
- case 'PLAY_MIDI':
66
- this.mbe = mb.getElement(mc.file, true);
67
- break;
68
- default:
69
- break;
70
- }
71
- }
72
-
73
- /**
74
- * Generates the objects that will play media
75
- */
76
- realize() {
77
- if (this.mbe) {
78
- this.mbe.build(mbe => {
79
- if (mbe.data && mbe.data.pause && !mbe.data.paused && !mbe.data.ended && mbe.data.currentTime)
80
- mbe.data.pause();
81
- if ((mbe.type === 'video' || mbe.type === 'anim') && mbe.data) {
82
- this.$visualComponent = $(mbe.data);
83
- this.$visualComponent.css('z-index', 20);
84
- }
85
- }, this.ps, false, this.mc.level);
86
- }
87
- }
88
-
89
- /**
90
- * Plays the media, realizing it if needed.
91
- * @param {module:boxes/ActiveBox.ActiveBox} [_setBx] - The active box where this media will be placed (when video)
92
- */
93
- playNow(_setBx) {
94
- // TODO: Remove unused param "_setBx"
95
- if (this.useAudioBuffer) {
96
- if (ActiveMediaPlayer.AUDIO_BUFFERS) {
97
- const $div = this.ps && this.ps.$div;
98
- const buffer = ActiveMediaPlayer.AUDIO_BUFFERS[this.mc.recBuffer];
99
- if (buffer) {
100
- if (this.mc.type === 'RECORD_AUDIO') {
101
- buffer.record($div);
102
- } else {
103
- buffer.play();
104
- }
105
- }
106
- }
107
- } else if (this.mbe) {
108
- this.mbe.build(() => {
109
- if (this.mbe.data) {
110
- if (this.mbe.type === 'midi') {
111
- this.mbe.data.playTo = this.mc.to || 0;
112
- } else {
113
- let armed = false;
114
- const $player = $(this.mbe.data);
115
- // Clear previous event handlers
116
- $player.off();
117
- // If there is a time fragment specified, prepare to stop when the `to` position is reached
118
- if (this.mc.to > 0) {
119
- $player.on('timeupdate', () => {
120
- if (armed && this.mbe.data.currentTime >= this.mc.to / 1000) {
121
- $player.off('timeupdate');
122
- this.mbe.data.pause();
123
- }
124
- });
125
- }
126
- // Launch the media despite of its readyState
127
- armed = true;
128
- }
129
- if (!this.mbe.data.paused && !this.mbe.data.ended && this.mbe.data.currentTime)
130
- this.mbe.data.pause();
131
- // Seek the media position
132
- this.mbe.data.currentTime = this.mc.from > 0 ? this.mc.from / 1000 : 0;
133
- this.mbe.data.play();
134
- }
135
- }, this.ps, true, this.mc.level);
136
- }
137
- }
138
-
139
- /**
140
- * Plays the media when available, without blocking the current thread.
141
- * @param {module:boxes/ActiveBox.ActiveBox} [setBx] - The active box where this media will be placed (when video)
142
- */
143
- play(setBx) {
144
- this.stopAllAudioBuffers();
145
- this.playNow(setBx);
146
- }
147
-
148
- /**
149
- * Stops the media playing
150
- */
151
- stop() {
152
- if (this.useAudioBuffer)
153
- this.stopAudioBuffer(this.mc.recBuffer);
154
- else if (this.mbe && this.mbe.data && this.mbe.data.pause && !this.mbe.data.paused && !this.mbe.data.ended && this.mbe.data.currentTime)
155
- this.mbe.data.pause();
156
- }
157
-
158
- /**
159
- * Frees all resources used by this player
160
- */
161
- clear() {
162
- this.stop();
163
- if (this.useAudioBuffer)
164
- this.clearAudioBuffer(this.mc.recBuffer);
165
- }
166
-
167
- /**
168
- * Clears the specified audio buffer
169
- * @param {number} buffer - Index of the buffer in {@link module:media/ActiveMediaPlayer.ActiveMediaPlayer#AUDIO_BUFFERS AUDIO_BUFFERS}
170
- */
171
- clearAudioBuffer(buffer) {
172
- if (ActiveMediaPlayer.AUDIO_BUFFERS &&
173
- buffer >= 0 && buffer < ActiveMediaPlayer.AUDIO_BUFFERS.length &&
174
- ActiveMediaPlayer.AUDIO_BUFFERS[buffer]) {
175
- ActiveMediaPlayer.AUDIO_BUFFERS[buffer].clear();
176
- ActiveMediaPlayer.AUDIO_BUFFERS[buffer] = null;
177
- }
178
- }
179
-
180
- /**
181
- * Clears all audio buffers
182
- */
183
- clearAllAudioBuffers() {
184
- if (ActiveMediaPlayer.AUDIO_BUFFERS)
185
- ActiveMediaPlayer.AUDIO_BUFFERS.forEach((_buffer, n) => this.clearAudioBuffer(n));
186
- }
187
-
188
- /**
189
- * Counts the number of active audio buffers
190
- * @returns {number}
191
- */
192
- countActiveBuffers() {
193
- return ActiveMediaPlayer.AUDIO_BUFFERS ? ActiveMediaPlayer.AUDIO_BUFFERS.reduce((c, ab) => c + ab ? 1 : 0, 0) : 0;
194
- }
195
-
196
- /**
197
- * Stops the playing or recording actions of all audio buffers
198
- */
199
- stopAllAudioBuffers() {
200
- if (ActiveMediaPlayer.AUDIO_BUFFERS)
201
- ActiveMediaPlayer.AUDIO_BUFFERS.forEach(ab => ab ? ab.stop() : null);
202
- }
203
-
204
- /**
205
- * Stops a specific audio buffer
206
- * @param {number} buffer - Index of the buffer in {@link module:media/ActiveMediaPlayer.ActiveMediaPlayer#AUDIO_BUFFERS AUDIO_BUFFERS}
207
- */
208
- stopAudioBuffer(buffer) {
209
- if (ActiveMediaPlayer.AUDIO_BUFFERS &&
210
- buffer >= 0 && buffer < ActiveMediaPlayer.AUDIO_BUFFERS.length &&
211
- ActiveMediaPlayer.AUDIO_BUFFERS[buffer])
212
- ActiveMediaPlayer.AUDIO_BUFFERS[buffer].stop();
213
- }
214
-
215
- /**
216
- * Checks the position of visual components after a displacement or resizing of its container
217
- * @param {module:boxes/ActiveBox.ActiveBox} _bxi - The container where this player is hosted
218
- */
219
- checkVisualComponentBounds(_bxi) {
220
- // does nothing
221
- }
222
-
223
- /**
224
- * Sets the visual component of this player visible or invisible
225
- * @param {boolean} _state - `true` for visible
226
- */
227
- setVisualComponentVisible(_state) {
228
- // TODO: Implement setVisualComponentVisible
229
- }
230
-
231
- /**
232
- * Sets the ActiveBox associated to this media player
233
- * @param {module:boxes/ActiveBox.ActiveBox} setBx - The new container of this media. Can be `null`.
234
- */
235
- linkTo(setBx) {
236
- this.bx = setBx;
237
- if (this.bx && this.$visualComponent)
238
- this.bx.setHostedComponent(this.$visualComponent);
239
- }
240
- }
241
-
242
- Object.assign(ActiveMediaPlayer.prototype, {
243
- /**
244
- * The MediaContent associated to this player.
245
- * @name module:media/ActiveMediaPlayer.ActiveMediaPlayer#mc
246
- * @type {module:media/MediaContent.MediaContent} */
247
- mc: null,
248
- /**
249
- * The player to which this player belongs.
250
- * @name module:media/ActiveMediaPlayer.ActiveMediaPlayer#ps
251
- * @type {module:JClicPlayer.JClicPlayer} */
252
- ps: null,
253
- /**
254
- * MediaPlayers should be linked to {@link module:boxes/ActiveBox.ActiveBox ActiveBox} objects.
255
- * @name module:media/ActiveMediaPlayer.ActiveMediaPlayer#bx
256
- * @type {module:boxes/ActiveBox.ActiveBox} */
257
- bx: null,
258
- /**
259
- * The visual component for videos, usually a `video` HTML element
260
- * @name module:media/ActiveMediaPlayer.ActiveMediaPlayer#$visualComponent
261
- * @type {external:jQuery} */
262
- $visualComponent: null,
263
- /**
264
- * When `true`, this player makes use of a recording audio buffer
265
- * @name module:media/ActiveMediaPlayer.ActiveMediaPlayer#useAudioBuffer
266
- * @type {boolean} */
267
- useAudioBuffer: false,
268
- /**
269
- * The {@link module:bads/MediaBagElement.MediaBagElement} containing the reference to the media to be played
270
- * @name module:media/ActiveMediaPlayer.ActiveMediaPlayer#mbe
271
- * @type {module:bags/MediaBagElement.MediaBagElement} */
272
- mbe: null,
273
- });
274
-
275
- /**
276
- * Recording of audio is enabled only when `navigator.getUserMedia` and `MediaRecorder` are defined
277
- * In 02-Mar-2016 this is implemented only in Firefox 41 and Chrome 49 or later.
278
- * See: {@link https://addpipe.com/blog/mediarecorder-api}
279
- * @type Boolean
280
- */
281
- ActiveMediaPlayer.REC_ENABLED = typeof MediaRecorder !== 'undefined' && typeof navigator !== 'undefined';
282
-
283
- if (ActiveMediaPlayer.REC_ENABLED) {
284
- navigator.getUserMedia = navigator.getUserMedia ||
285
- navigator.webkitGetUserMedia ||
286
- navigator.mozGetUserMedia ||
287
- navigator.msGetUserMedia;
288
- }
289
-
290
- /**
291
- * Audio buffers used for recording and playing voice are stored in a static array because
292
- * they are common to all instances of {@link module:media/ActiveMediaPlayer.ActiveMediaPlayer ActiveMediaPlayer}
293
- * Only initialized when {@link module:media/ActiveMediaPlayer.ActiveMediaPlayer#REC_ENABLED REC_ENABLED} is `true`.
294
- * @type {external:AudioBuffer[]} */
295
- ActiveMediaPlayer.AUDIO_BUFFERS = ActiveMediaPlayer.REC_ENABLED ? [] : null;
296
-
297
- export default ActiveMediaPlayer;
@@ -1,219 +0,0 @@
1
- /**
2
- * File : media/EventSoundsElement.js
3
- * Created : 01/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 navigator, window, document, Blob, URL, MediaRecorder */
33
-
34
- import { log } from '../Utils.js';
35
-
36
- /**
37
- * The AudioBuffer object provides sound recording and replaying to activities.
38
- */
39
- export class AudioBuffer {
40
- /**
41
- * AudioBuffer constructor
42
- * @param {number} [seconds] - The maximum amount of time allowed to be recorded by this AudioBuffer
43
- */
44
- constructor(seconds) {
45
- if (navigator && navigator.mediaDevices && navigator.mediaDevices.getUserMedia)
46
- this.enabled = true;
47
- if (seconds)
48
- this.seconds = seconds;
49
- this.chunks = [];
50
- }
51
-
52
- /**
53
- * Starts playing the currently recorded audio, if any.
54
- */
55
- play() {
56
- this.stop();
57
- if (this.mediaPlayer) {
58
- this.mediaPlayer.currentTime = 0;
59
- this.mediaPlayer.play();
60
- } else {
61
- this.playWhenFinished = true;
62
- }
63
- }
64
-
65
- /**
66
- * Stops the current operation, either recording or playing audio
67
- */
68
- stop() {
69
- if (this.mediaRecorder && this.mediaRecorder.state === 'recording')
70
- this.mediaRecorder.stop();
71
- else if (this.mediaPlayer && !this.mediaPlayer.paused)
72
- this.mediaPlayer.pause();
73
- }
74
-
75
- /**
76
- * Starts recording audio, or stops the recording if already started.
77
- * @param {external:jQuery} [$div] - Optional `div` element where the recording is performed, as a jQuery ref.
78
- */
79
- record($div) {
80
- if (this.mediaRecorder && this.mediaRecorder.state === 'recording')
81
- this.mediaRecorder.stop();
82
- else if (this.enabled) {
83
- this.stop();
84
- this.mediaPlayer = null;
85
-
86
- navigator.mediaDevices.getUserMedia({ audio: true, video: false })
87
- .then(mediaStream => {
88
-
89
- this.mediaRecorder = new MediaRecorder(mediaStream);
90
-
91
- this.mediaRecorder.ondataavailable = ev => this.chunks.push(ev.data);
92
-
93
- this.mediaRecorder.onerror = err => {
94
- log('error', `Error recording audio: ${err}`);
95
- this.mediaRecorder = null;
96
- };
97
-
98
- this.mediaRecorder.onstart = () => {
99
- log('debug', 'Recording audio started');
100
- this.visualFeedbak(true, $div);
101
- };
102
-
103
- this.mediaRecorder.onstop = () => {
104
- log('debug', 'Recording audio finished');
105
- this.visualFeedbak(false, $div);
106
-
107
- if (this.timeoutID) {
108
- window.clearTimeout(this.timeoutID);
109
- this.timeoutID = null;
110
- }
111
-
112
- const options = {};
113
- if (this.chunks.length > 0 && this.chunks[0].type)
114
- options.type = this.chunks[0].type;
115
- const blob = new Blob(this.chunks, options);
116
- this.chunks = [];
117
- this.mediaPlayer = document.createElement('audio');
118
- this.mediaPlayer.src = URL.createObjectURL(blob);
119
- this.mediaPlayer.pause();
120
- this.mediaRecorder = null;
121
- if (this.playWhenFinished) {
122
- this.playWhenFinished = false;
123
- this.mediaPlayer.play();
124
- }
125
- };
126
-
127
- this.mediaRecorder.onwarning = ev => log('warn', `Warning recording audio: ${ev}`);
128
-
129
- this.playWhenFinished = false;
130
-
131
- this.mediaRecorder.start();
132
-
133
- this.timeoutID = window.setTimeout(() => {
134
- if (this.mediaRecorder);
135
- this.mediaRecorder.stop();
136
- }, this.seconds * 1000);
137
- })
138
- .catch(err => {
139
- log('error', err.toString());
140
- this.visualFeedbak(false, $div);
141
- });
142
- }
143
- }
144
-
145
- /**
146
- * Set visual feedback to the user while the system is recording audio
147
- * Currently changes the cursor pointer associated to the HTML element
148
- * containing the recorder.
149
- * @param {boolean} enabled - Flag indicating if the visual feedback should be active or inactive
150
- * @param {external:jQuery} [$div] - Optional `div` element where the recording is performed, as a jQuery ref.
151
- */
152
- visualFeedbak(enabled, $div) {
153
- if ($div)
154
- $div.css('cursor', enabled ? 'progress' : 'inherit');
155
- }
156
-
157
- /**
158
- * Clears all data associated to this AudioBuffer
159
- */
160
- clear() {
161
- this.stop();
162
- this.mediaPlayer = null;
163
- }
164
- }
165
-
166
- Object.assign(AudioBuffer.prototype, {
167
- /**
168
- * AudioBuffer is enabled only in browsers with `navigator.MediaDevices.getuserMedia`
169
- * @name module:media/AudioBuffer.AudioBuffer#enabled
170
- * @type {boolean}
171
- */
172
- enabled: false,
173
- /**
174
- * Maximum length of recordings allowed to this AudioBuffer (in seconds)
175
- * @name module:media/AudioBuffer.AudioBuffer#seconds
176
- * @type {number}
177
- */
178
- seconds: 20,
179
- /**
180
- * The object used to record audio data and convert it to a valid stream for the {@link module:media/ActiveMediaPlayer.ActiveMediaPlayer ActiveMediaPlayer}
181
- * @name module:media/AudioBuffer.AudioBuffer#mediaRecorder
182
- * @type {external:MediaRecorder}
183
- */
184
- mediaRecorder: null,
185
- /**
186
- * Array of data chunks collected during the recording
187
- * @name module:media/AudioBuffer.AudioBuffer#chunks
188
- * @type {external:Blob[]}
189
- */
190
- chunks: null,
191
- /**
192
- * The HTML audio element used to play the recorded sound
193
- * @name module:media/AudioBuffer.AudioBuffer#mediaPlayer
194
- * @type {external:HTMLAudioElement}
195
- */
196
- mediaPlayer: null,
197
- /**
198
- * The identifier of the timer launched to stop the recording when the maximum time is exceeded.
199
- * This member is `null` when no timeout function is associated to this AudioBuffer
200
- * @name module:media/AudioBuffer.AudioBuffer#timeoutID
201
- * @type {number}
202
- */
203
- timeoutID: null,
204
- /**
205
- * Instructs this AudioBuffer recorder to start playing the collected audio at the end of the
206
- * current `mediaRecorder` task.
207
- * @name module:media/AudioBuffer.AudioBuffer#playWhenFinished
208
- * @type {boolean}
209
- */
210
- playWhenFinished: false,
211
- });
212
-
213
- /**
214
- * Maximum amount of time allowed for recordings (in seconds)
215
- * @type {number}
216
- */
217
- AudioBuffer.MAX_RECORD_LENGTH = 180;
218
-
219
- export default AudioBuffer;
@@ -1,169 +0,0 @@
1
- /**
2
- * File : media/EventSounds.js
3
- * Created : 01/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
- import $ from 'jquery';
33
- import EventSoundsElement from './EventSoundsElement.js';
34
- import { getTriState, getAttr, setAttr, DEFAULT } from '../Utils.js';
35
-
36
- // Use Webpack to import MP3 files
37
- import start from './sounds/start.mp3';
38
- import click from './sounds/click.mp3';
39
- import actionOk from './sounds/actionOk.mp3';
40
- import actionError from './sounds/actionError.mp3';
41
- import finishedOk from './sounds/finishedOk.mp3';
42
- import finishedError from './sounds/finishedError.mp3';
43
-
44
- /**
45
- * The EventSounds objects contains specific sounds to be played when JClic events are fired:
46
- * - start
47
- * - click
48
- * - actionError
49
- * - actionOk
50
- * - finishedError
51
- * - finishedOk
52
- *
53
- * The sounds are stored in an array of {@link module:media/EventSoundsElement EventSoundsElement} objects.
54
- */
55
- export class EventSounds {
56
- /**
57
- * EventSounds constructor
58
- * @param {module:media/EventSounds.EventSounds} [parent] - Another EventSounds object that will act as a parent of this one,
59
- * used to resolve which sound must be played for events when not defined here.
60
- */
61
- constructor(parent) {
62
- if (parent) {
63
- this.elements = Object.assign({}, this.elements, parent.elements);
64
- this.enabled = parent.enabled;
65
- }
66
- }
67
-
68
- /**
69
- * Reads the object properties from an XML element
70
- * @param {external:jQuery} $xml - The XML element to be parsed
71
- */
72
- setProperties($xml) {
73
- this.enabled = getTriState($xml.attr('enabled'), this.enabled);
74
- $xml.children().each((_n, child) => {
75
- const id = child.getAttribute('id');
76
- this.elements[id] = new EventSoundsElement(id);
77
- this.elements[id].setProperties($(child));
78
- });
79
- return this;
80
- }
81
-
82
- /**
83
- * Gets a object with the basic attributes needed to rebuild this instance excluding functions,
84
- * parent references, constants and also attributes retaining the default value.
85
- * The resulting object is commonly usued to serialize elements in JSON format.
86
- * @returns {object} - The resulting object, with minimal attrributes
87
- */
88
- getAttributes() {
89
- return getAttr(this, [
90
- `enabled|${DEFAULT}`,
91
- 'elements',
92
- ]);
93
- }
94
-
95
- /**
96
- * Reads the properties of this EventSounds from a data object
97
- * @param {object} data - The data object to be parsed
98
- * @returns {module:media/EventSounds.EventSounds}
99
- */
100
- setAttributes(data) {
101
- return setAttr(this, data, [
102
- 'enabled',
103
- { key: 'elements', fn: EventSoundsElement, group: 'object' },
104
- ]);
105
- }
106
-
107
- /**
108
- * Instantiates the audio objects needed to play event sounds
109
- * @param {module:JClicPlayer.JClicPlayer} ps
110
- * @param {module:bags/MediaBag.MediaBag} mediaBag
111
- */
112
- realize(ps, mediaBag) {
113
- // Values are {EventSoundElement} objects
114
- $.each(this.elements, (key, value) => value.realize(ps, mediaBag));
115
- }
116
-
117
- /**
118
- * Plays a specific event sound
119
- * @param {string} eventName - The identifier of the event to be played
120
- */
121
- play(eventName) {
122
- if (this.globalEnabled && this.enabled) {
123
- const sound = this.elements[eventName];
124
- if (sound && sound.enabled)
125
- sound.play();
126
- }
127
- }
128
- }
129
-
130
- /**
131
- * Audio data for default event sounds
132
- * @name module:media/EventSounds.EventSounds.MEDIA
133
- * @type {object} */
134
- EventSounds.MEDIA = {
135
- start,
136
- click,
137
- actionOk,
138
- actionError,
139
- finishedOk,
140
- finishedError,
141
- };
142
-
143
- Object.assign(EventSounds.prototype, {
144
- /**
145
- * Collection of {@link module:media/EventSoundsElement EventSoundsElement} objects
146
- * @name module:media/EventSounds.EventSounds#elements
147
- * @type {object} */
148
- elements: {
149
- start: new EventSoundsElement('start', EventSounds.MEDIA.start),
150
- click: new EventSoundsElement('click', EventSounds.MEDIA.click),
151
- actionOk: new EventSoundsElement('actionOk', EventSounds.MEDIA.actionOk),
152
- actionError: new EventSoundsElement('actionError', EventSounds.MEDIA.actionError),
153
- finishedOk: new EventSoundsElement('finishedOk', EventSounds.MEDIA.finishedOk),
154
- finishedError: new EventSoundsElement('finishedError', EventSounds.MEDIA.finishedError)
155
- },
156
- /**
157
- * Whether this event sounds are enabled or not
158
- * @name module:media/EventSounds.EventSounds#enabled
159
- * @type {number} */
160
- enabled: DEFAULT,
161
- /**
162
- * This attribute is intended to be used at prototype level, to indicate a globally disabled
163
- * or enabled state.
164
- * @name module:media/EventSounds.EventSounds#globalEnabled
165
- * @type {boolean} */
166
- globalEnabled: true,
167
- });
168
-
169
- export default EventSounds;