jclic 2.1.21 → 2.1.23

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 (175) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/dist/jclic-node.js +9 -8
  3. package/dist/jclic-node.js.map +1 -1
  4. package/dist/jclic.min.js +2 -2
  5. package/dist/jclic.min.js.map +1 -1
  6. package/package.json +4 -4
  7. package/src/GlobalData.js +1 -1
  8. package/src/JClicPlayer.js +2 -2
  9. package/src/bags/MediaBag.js +6 -5
  10. package/dist/1078.jclic-node.js +0 -282
  11. package/dist/1078.jclic-node.js.map +0 -1
  12. package/dist/1196.jclic-node.js +0 -808
  13. package/dist/1196.jclic-node.js.map +0 -1
  14. package/dist/1253.jclic-node.js +0 -1432
  15. package/dist/1253.jclic-node.js.map +0 -1
  16. package/dist/13.jclic-node.js +0 -103
  17. package/dist/13.jclic-node.js.map +0 -1
  18. package/dist/1567.jclic-node.js +0 -2313
  19. package/dist/1567.jclic-node.js.map +0 -1
  20. package/dist/1588.jclic-node.js +0 -602
  21. package/dist/1588.jclic-node.js.map +0 -1
  22. package/dist/1725.jclic-node.js +0 -836
  23. package/dist/1725.jclic-node.js.map +0 -1
  24. package/dist/1731.jclic-node.js +0 -438
  25. package/dist/1731.jclic-node.js.map +0 -1
  26. package/dist/1842.jclic-node.js +0 -651
  27. package/dist/1842.jclic-node.js.map +0 -1
  28. package/dist/2160.jclic-node.js +0 -1016
  29. package/dist/2160.jclic-node.js.map +0 -1
  30. package/dist/222.jclic-node.js +0 -129
  31. package/dist/222.jclic-node.js.map +0 -1
  32. package/dist/2316.jclic-node.js +0 -949
  33. package/dist/2316.jclic-node.js.map +0 -1
  34. package/dist/2355.jclic-node.js +0 -371
  35. package/dist/2355.jclic-node.js.map +0 -1
  36. package/dist/2366.jclic-node.js +0 -431
  37. package/dist/2366.jclic-node.js.map +0 -1
  38. package/dist/2379.jclic-node.js +0 -202
  39. package/dist/2379.jclic-node.js.map +0 -1
  40. package/dist/2437.jclic-node.js +0 -450
  41. package/dist/2437.jclic-node.js.map +0 -1
  42. package/dist/2531.jclic-node.js +0 -869
  43. package/dist/2531.jclic-node.js.map +0 -1
  44. package/dist/2608.jclic-node.js +0 -160
  45. package/dist/2608.jclic-node.js.map +0 -1
  46. package/dist/2715.jclic-node.js +0 -554
  47. package/dist/2715.jclic-node.js.map +0 -1
  48. package/dist/277.jclic-node.js +0 -22
  49. package/dist/277.jclic-node.js.map +0 -1
  50. package/dist/2921.jclic-node.js +0 -660
  51. package/dist/2921.jclic-node.js.map +0 -1
  52. package/dist/2952.jclic-node.js +0 -101
  53. package/dist/2952.jclic-node.js.map +0 -1
  54. package/dist/3018.jclic-node.js +0 -421
  55. package/dist/3018.jclic-node.js.map +0 -1
  56. package/dist/3019.jclic-node.js +0 -682
  57. package/dist/3019.jclic-node.js.map +0 -1
  58. package/dist/3231.jclic-node.js +0 -274
  59. package/dist/3231.jclic-node.js.map +0 -1
  60. package/dist/331.jclic-node.js +0 -115
  61. package/dist/331.jclic-node.js.map +0 -1
  62. package/dist/3391.jclic-node.js +0 -276
  63. package/dist/3391.jclic-node.js.map +0 -1
  64. package/dist/3502.jclic-node.js +0 -671
  65. package/dist/3502.jclic-node.js.map +0 -1
  66. package/dist/3653.jclic-node.js +0 -982
  67. package/dist/3653.jclic-node.js.map +0 -1
  68. package/dist/371.jclic.min.js +0 -2
  69. package/dist/371.jclic.min.js.map +0 -1
  70. package/dist/3856.jclic-node.js +0 -575
  71. package/dist/3856.jclic-node.js.map +0 -1
  72. package/dist/4112.jclic-node.js +0 -659
  73. package/dist/4112.jclic-node.js.map +0 -1
  74. package/dist/4123.jclic-node.js +0 -910
  75. package/dist/4123.jclic-node.js.map +0 -1
  76. package/dist/427.jclic-node.js +0 -894
  77. package/dist/427.jclic-node.js.map +0 -1
  78. package/dist/4483.jclic-node.js +0 -327
  79. package/dist/4483.jclic-node.js.map +0 -1
  80. package/dist/4548.jclic-node.js +0 -1078
  81. package/dist/4548.jclic-node.js.map +0 -1
  82. package/dist/466.jclic-node.js +0 -99
  83. package/dist/466.jclic-node.js.map +0 -1
  84. package/dist/485.jclic-node.js +0 -783
  85. package/dist/485.jclic-node.js.map +0 -1
  86. package/dist/4921.jclic-node.js +0 -500
  87. package/dist/4921.jclic-node.js.map +0 -1
  88. package/dist/5091.jclic-node.js +0 -239
  89. package/dist/5091.jclic-node.js.map +0 -1
  90. package/dist/520.jclic-node.js +0 -550
  91. package/dist/520.jclic-node.js.map +0 -1
  92. package/dist/5312.jclic-node.js +0 -1126
  93. package/dist/5312.jclic-node.js.map +0 -1
  94. package/dist/5338.jclic-node.js +0 -212
  95. package/dist/5338.jclic-node.js.map +0 -1
  96. package/dist/5344.jclic-node.js +0 -229
  97. package/dist/5344.jclic-node.js.map +0 -1
  98. package/dist/5550.jclic-node.js +0 -238
  99. package/dist/5550.jclic-node.js.map +0 -1
  100. package/dist/5626.jclic-node.js +0 -614
  101. package/dist/5626.jclic-node.js.map +0 -1
  102. package/dist/5977.jclic-node.js +0 -1081
  103. package/dist/5977.jclic-node.js.map +0 -1
  104. package/dist/6148.jclic-node.js +0 -345
  105. package/dist/6148.jclic-node.js.map +0 -1
  106. package/dist/6176.jclic-node.js +0 -481
  107. package/dist/6176.jclic-node.js.map +0 -1
  108. package/dist/6221.jclic-node.js +0 -1072
  109. package/dist/6221.jclic-node.js.map +0 -1
  110. package/dist/6238.jclic-node.js +0 -718
  111. package/dist/6238.jclic-node.js.map +0 -1
  112. package/dist/6454.jclic-node.js +0 -1413
  113. package/dist/6454.jclic-node.js.map +0 -1
  114. package/dist/6565.jclic-node.js +0 -294
  115. package/dist/6565.jclic-node.js.map +0 -1
  116. package/dist/6579.jclic-node.js +0 -719
  117. package/dist/6579.jclic-node.js.map +0 -1
  118. package/dist/6715.jclic-node.js +0 -148
  119. package/dist/6715.jclic-node.js.map +0 -1
  120. package/dist/6777.jclic-node.js +0 -171
  121. package/dist/6777.jclic-node.js.map +0 -1
  122. package/dist/6782.jclic-node.js +0 -1611
  123. package/dist/6782.jclic-node.js.map +0 -1
  124. package/dist/6847.jclic-node.js +0 -601
  125. package/dist/6847.jclic-node.js.map +0 -1
  126. package/dist/6856.jclic-node.js +0 -252
  127. package/dist/6856.jclic-node.js.map +0 -1
  128. package/dist/696.jclic-node.js +0 -1821
  129. package/dist/696.jclic-node.js.map +0 -1
  130. package/dist/698.jclic-node.js +0 -583
  131. package/dist/698.jclic-node.js.map +0 -1
  132. package/dist/704.jclic-node.js +0 -80
  133. package/dist/704.jclic-node.js.map +0 -1
  134. package/dist/7046.jclic-node.js +0 -735
  135. package/dist/7046.jclic-node.js.map +0 -1
  136. package/dist/7220.jclic-node.js +0 -156
  137. package/dist/7220.jclic-node.js.map +0 -1
  138. package/dist/7257.jclic-node.js +0 -931
  139. package/dist/7257.jclic-node.js.map +0 -1
  140. package/dist/743.jclic-node.js +0 -583
  141. package/dist/743.jclic-node.js.map +0 -1
  142. package/dist/757.jclic-node.js +0 -1072
  143. package/dist/757.jclic-node.js.map +0 -1
  144. package/dist/7781.jclic-node.js +0 -202
  145. package/dist/7781.jclic-node.js.map +0 -1
  146. package/dist/7912.jclic-node.js +0 -2103
  147. package/dist/7912.jclic-node.js.map +0 -1
  148. package/dist/827.jclic-node.js +0 -708
  149. package/dist/827.jclic-node.js.map +0 -1
  150. package/dist/8276.jclic-node.js +0 -409
  151. package/dist/8276.jclic-node.js.map +0 -1
  152. package/dist/8322.jclic-node.js +0 -498
  153. package/dist/8322.jclic-node.js.map +0 -1
  154. package/dist/8641.jclic-node.js +0 -360
  155. package/dist/8641.jclic-node.js.map +0 -1
  156. package/dist/8837.jclic-node.js +0 -651
  157. package/dist/8837.jclic-node.js.map +0 -1
  158. package/dist/8895.jclic-node.js +0 -151
  159. package/dist/8895.jclic-node.js.map +0 -1
  160. package/dist/9072.jclic-node.js +0 -1285
  161. package/dist/9072.jclic-node.js.map +0 -1
  162. package/dist/9078.jclic-node.js +0 -935
  163. package/dist/9078.jclic-node.js.map +0 -1
  164. package/dist/9103.jclic-node.js +0 -718
  165. package/dist/9103.jclic-node.js.map +0 -1
  166. package/dist/9359.jclic-node.js +0 -145
  167. package/dist/9359.jclic-node.js.map +0 -1
  168. package/dist/9409.jclic-node.js +0 -921
  169. package/dist/9409.jclic-node.js.map +0 -1
  170. package/dist/9513.jclic-node.js +0 -720
  171. package/dist/9513.jclic-node.js.map +0 -1
  172. package/dist/9704.jclic-node.js +0 -81
  173. package/dist/9704.jclic-node.js.map +0 -1
  174. package/dist/9950.jclic-node.js +0 -827
  175. package/dist/9950.jclic-node.js.map +0 -1
@@ -1,1821 +0,0 @@
1
- "use strict";
2
- exports.id = 696;
3
- exports.ids = [696,4483];
4
- exports.modules = {
5
-
6
- /***/ 696:
7
- /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
8
-
9
- /* harmony export */ __webpack_require__.d(__webpack_exports__, {
10
- /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
11
- /* harmony export */ });
12
- /* unused harmony export JClicPlayer */
13
- /* harmony import */ var jquery__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(7750);
14
- /* harmony import */ var jquery__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(jquery__WEBPACK_IMPORTED_MODULE_0__);
15
- /* harmony import */ var jszip__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(8194);
16
- /* harmony import */ var jszip__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(jszip__WEBPACK_IMPORTED_MODULE_1__);
17
- /* harmony import */ var jszip_utils__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(6402);
18
- /* harmony import */ var jszip_utils__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(jszip_utils__WEBPACK_IMPORTED_MODULE_2__);
19
- /* harmony import */ var _Utils_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(1253);
20
- /* harmony import */ var _AWT_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(7912);
21
- /* harmony import */ var _PlayerHistory_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(4483);
22
- /* harmony import */ var _media_ActiveMediaBag_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(827);
23
- /* harmony import */ var _skins_Skin_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(757);
24
- /* harmony import */ var _media_EventSounds_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(5338);
25
- /* harmony import */ var _project_JClicProject_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(9950);
26
- /* harmony import */ var _bags_JumpInfo_js__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(7220);
27
- /* harmony import */ var _boxes_ActiveBoxContent_js__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(9072);
28
- /* harmony import */ var _report_Reporter_js__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(6782);
29
- /* harmony import */ var _bags_MediaBagElement_js__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(1196);
30
- /**
31
- * File : JClicPlayer.js
32
- * Created : 28/04/2015
33
- * By : Francesc Busquets <francesc@gmail.com>
34
- *
35
- * JClic.js
36
- * An HTML5 player of JClic activities
37
- * https://projectestac.github.io/jclic.js
38
- *
39
- * @source https://github.com/projectestac/jclic.js
40
- *
41
- * @license EUPL-1.2
42
- * @licstart
43
- * (c) 2000-2022 Educational Telematic Network of Catalonia (XTEC)
44
- *
45
- * Licensed under the EUPL, Version 1.1 or -as soon they will be approved by
46
- * the European Commission- subsequent versions of the EUPL (the "Licence");
47
- * You may not use this work except in compliance with the Licence.
48
- *
49
- * You may obtain a copy of the Licence at:
50
- * https://joinup.ec.europa.eu/software/page/eupl
51
- *
52
- * Unless required by applicable law or agreed to in writing, software
53
- * distributed under the Licence is distributed on an "AS IS" basis, WITHOUT
54
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
55
- * Licence for the specific language governing permissions and limitations
56
- * under the Licence.
57
- * @licend
58
- * @module
59
- */
60
-
61
- /* global JSON, Promise, location, window, document */
62
-
63
-
64
-
65
-
66
-
67
-
68
-
69
-
70
-
71
-
72
-
73
-
74
-
75
-
76
-
77
-
78
- /**
79
- * JClicPlayer is one of the the main classes of the JClic system. It implements the
80
- * {@link http://projectestac.github.io/jclic/apidoc/edu/xtec/jclic/PlayStation.html PlayStation}
81
- * interface, needed to host JClic activities.
82
- * JClicPlayer offers to {@link module:Activity.ActivityPanel ActivityPanel} objects all the necessary resources and functions:
83
- * media bags (to load and realize images and other media contents), sequence control, management
84
- * of the reporting system, user interface, display of system messages, etc.
85
- * @extends module:AWT.Container
86
- */
87
- class JClicPlayer extends _AWT_js__WEBPACK_IMPORTED_MODULE_4__/* .Container */ .mc {
88
-
89
- /**
90
- * JClicPlayer constructor
91
- * @param {external:jQuery} $topDiv - The HTML `div` element where this JClicPlayer will deploy.
92
- * @param {object} [options] - A set of optional customized options.
93
- */
94
- constructor($topDiv, options) {
95
-
96
- // JClicPlayer extends Container
97
- super();
98
- // Build cascading options
99
- options = (0,_Utils_js__WEBPACK_IMPORTED_MODULE_3__/* .init */ .Ts)(options);
100
- this.options = jquery__WEBPACK_IMPORTED_MODULE_0___default().extend(Object.create(this.options), options);
101
- // Generate unique ID
102
- this.id = `JC${(0x10000 + Math.round(Math.random() * 0xFFFF)).toString(16).toUpperCase().substring(1)}`;
103
- // Identify the HTML element where this player will deploy
104
- this.$topDiv = $topDiv || jquery__WEBPACK_IMPORTED_MODULE_0___default()('<div/>');
105
- // Avoid side effects of 'align=center' in old HTML pages
106
- this.$topDiv.css({ 'text-align': 'initial' });
107
-
108
- // Special case: $topDiv inside a TD (like in http://clic.xtec.cat/gali)
109
- if (this.$topDiv.parent().is('td')) {
110
- // Set explicit width and height to fill-in the TD
111
- this.$topDiv.css({
112
- width: (0,_Utils_js__WEBPACK_IMPORTED_MODULE_3__/* .toCssSize */ .SV)(this.options.width, null, null, '100%'),
113
- height: (0,_Utils_js__WEBPACK_IMPORTED_MODULE_3__/* .toCssSize */ .SV)(this.options.height, null, null, '100%'),
114
- });
115
- }
116
-
117
- // Build the main container
118
- this.$mainContainer = jquery__WEBPACK_IMPORTED_MODULE_0___default()('<div/>', { class: 'JClicContainer', id: this.id })
119
- .css({ width: '100%', height: '100%' })
120
- .appendTo(this.$topDiv);
121
-
122
- // Intitialize other elements
123
- this.localFS = location && location.protocol === 'file:';
124
- this.$div = jquery__WEBPACK_IMPORTED_MODULE_0___default()('<div/>', { class: 'JClicPlayer' });
125
- this.project = new _project_JClicProject_js__WEBPACK_IMPORTED_MODULE_9__["default"]();
126
- this.activeMediaBag = new _media_ActiveMediaBag_js__WEBPACK_IMPORTED_MODULE_6__["default"]();
127
- this.counterVal = { score: 0, actions: 0, time: 0 };
128
- this.bgImageOrigin = new _AWT_js__WEBPACK_IMPORTED_MODULE_4__/* .Point */ .bR();
129
- this.buildActions();
130
- this.history = new _PlayerHistory_js__WEBPACK_IMPORTED_MODULE_5__["default"](this);
131
- this.audioEnabled = this.options.audioEnabled;
132
- this.navButtonsAlways = this.options.navButtonsAlways;
133
- this.defaultSkin = _skins_Skin_js__WEBPACK_IMPORTED_MODULE_7__["default"].getSkin(this.options.skin, this);
134
- this.setSkin(_skins_Skin_js__WEBPACK_IMPORTED_MODULE_7__["default"].getSkin('@empty.xml', this));
135
- this.initTimers();
136
- this.listenTouchEvents();
137
- (0,_Utils_js__WEBPACK_IMPORTED_MODULE_3__/* .log */ .Rm)('info', 'JClicPlayer ready');
138
- }
139
-
140
- /**
141
- *
142
- * Detects swipe-right, swipe-left and double touch gestures on touch devices,
143
- * associating them with 'next activity', 'previous activity' and 'toggle full screen' actions
144
- */
145
- listenTouchEvents() {
146
-
147
- // Enable listeners only in touch devices
148
- //if ('ontouchstart' in window) {
149
-
150
- let startTouch = null;
151
- let startTouchTime = 0;
152
- let thisDiv = this.$div[0];
153
- const { minSwipeX, maxSwipeY, rightToLeft } = this.options;
154
-
155
- // Generic handler for touch events
156
- const touchEventHandler = event => {
157
- // Process only single-finger events targeted to our main 'div'
158
- if (event.target === thisDiv && event.changedTouches && event.changedTouches.length === 1) {
159
- const touch = event.changedTouches[0];
160
- const dx = startTouch ? touch.clientX - startTouch.clientX : 0;
161
- const dy = startTouch ? touch.clientY - startTouch.clientY : 0;
162
- const dist = Math.sqrt(dx * dx + dy * dy);
163
-
164
- switch (event.type) {
165
- case 'touchstart':
166
- const currentTime = new Date();
167
- // Detect double taps, done in less than 800 ms and at short distance
168
- if (
169
- document && document.fullscreenEnabled
170
- && startTouch && startTouchTime
171
- && currentTime - startTouchTime < 800
172
- && dist < minSwipeX
173
- ) {
174
- event.preventDefault();
175
- (0,_Utils_js__WEBPACK_IMPORTED_MODULE_3__/* .log */ .Rm)('info', 'Toggle full screen mode from double touch');
176
- this.skin.setScreenFull();
177
- startTouch = null;
178
- }
179
- else {
180
- startTouch = touch;
181
- startTouchTime = currentTime;
182
- }
183
- break;
184
-
185
- case 'touchend':
186
- // Discard non-horizontal gestures and those that do not have sufficient length
187
- if (startTouch && Math.abs(dx) > minSwipeX && Math.abs(dy) < maxSwipeY) {
188
- const actionName = dx < 0 && !rightToLeft ? 'next' : 'prev';
189
- const action = this.actions[actionName];
190
- if (action && action.enabled) {
191
- event.preventDefault();
192
- (0,_Utils_js__WEBPACK_IMPORTED_MODULE_3__/* .log */ .Rm)('info', `Performing action "${actionName}" from touch gesture`);
193
- action.actionPerformed(event);
194
- }
195
- startTouch = null;
196
- }
197
- // Cancel double touch detection when long gestures detected
198
- else if (dist > minSwipeX)
199
- startTouch = null;
200
- break;
201
-
202
- case 'touchcancel':
203
- startTouch = null;
204
- break;
205
- }
206
- }
207
- else
208
- // Cancel any started gesture
209
- startTouch = null;
210
- };
211
-
212
- // Handle touch events
213
- thisDiv.addEventListener('touchstart', touchEventHandler);
214
- thisDiv.addEventListener('touchend', touchEventHandler);
215
- thisDiv.addEventListener('touchcancel', touchEventHandler);
216
- //}
217
- }
218
-
219
- /**
220
- * Generates an unique ID for elements being used with this player
221
- * @param {string} lb - The element's label
222
- * @returns {string}
223
- */
224
- getUniqueId(lb) {
225
- return `${this.id}-${lb}`;
226
- }
227
-
228
- /**
229
- * Builds the {@link module:AWT.Action} objects for this player
230
- */
231
- buildActions() {
232
- this.actions = {
233
- 'next': new _AWT_js__WEBPACK_IMPORTED_MODULE_4__/* .Action */ .rc('next', () => this.history.processJump(this.project.activitySequence.getJump(false, this.reporter), false)),
234
- 'prev': new _AWT_js__WEBPACK_IMPORTED_MODULE_4__/* .Action */ .rc('prev', () => this.history.processJump(this.project.activitySequence.getJump(true, this.reporter), false)),
235
- 'return': new _AWT_js__WEBPACK_IMPORTED_MODULE_4__/* .Action */ .rc('return', () => this.history.pop()),
236
- 'reset': new _AWT_js__WEBPACK_IMPORTED_MODULE_4__/* .Action */ .rc('reset', () => { if (this.actPanel && this.actPanel.act.canReinit()) this.initActivity(); }),
237
- 'help': new _AWT_js__WEBPACK_IMPORTED_MODULE_4__/* .Action */ .rc('help', () => { if (this.actPanel) this.actPanel.showHelp(); }),
238
- 'info': new _AWT_js__WEBPACK_IMPORTED_MODULE_4__/* .Action */ .rc('info', () => {
239
- if (this.actPanel && this.actPanel.act.hasInfo()) {
240
- if (this.actPanel.act.infoUrl)
241
- this.displayURL(this.act.infoUrl, true);
242
- else if (this.actPanel.act.infoCmd)
243
- this.runCmd(this.actPanel.act.infoCmd);
244
- }
245
- }),
246
- 'reports': new _AWT_js__WEBPACK_IMPORTED_MODULE_4__/* .Action */ .rc('reports', () => this.showReports()),
247
- 'audio': new _AWT_js__WEBPACK_IMPORTED_MODULE_4__/* .Action */ .rc('audio', () => {
248
- this.audioEnabled = !this.audioEnabled;
249
- if (!this.audioEnabled)
250
- this.stopMedia();
251
- _media_EventSounds_js__WEBPACK_IMPORTED_MODULE_8__["default"].prototype.globalEnabled = this.audioEnabled;
252
- })
253
- };
254
-
255
- jquery__WEBPACK_IMPORTED_MODULE_0___default().each(this.actions, (key, value) => {
256
- value.addStatusListener(action => { if (this.skin) this.skin.actionStatusChanged(action); });
257
- });
258
- }
259
-
260
- /**
261
- * Resets the main components of this player
262
- */
263
- reset() {
264
- (0,_Utils_js__WEBPACK_IMPORTED_MODULE_3__/* .log */ .Rm)('info', 'Restoring player');
265
- this.removeActivity();
266
- this.end();
267
- this.activeMediaBag = new _media_ActiveMediaBag_js__WEBPACK_IMPORTED_MODULE_6__["default"]();
268
- this.history.clearHistory();
269
- this.setSkin(null);
270
- this.setMsg(null);
271
- this.setCounterValue('score', 0);
272
- this.setCounterValue('actions', 0);
273
- this.setCounterValue('time', 0);
274
- if (this.skin)
275
- this.skin.setWaitCursor('reset');
276
- }
277
-
278
- /**
279
- * Instructs the player to stop working
280
- */
281
- stop() {
282
- this.stopMedia(-1);
283
- }
284
-
285
- /**
286
- * Executes miscellaneous finalization routines.
287
- * @returns {external:Promise} - A promise to be fullfilled when all pending tasks are finished.
288
- */
289
- end() {
290
- let result = null;
291
- this.stopMedia();
292
- this.closeHelpWindow();
293
- if (this.reporter) {
294
- result = this.reporter.end();
295
- this.reporter = null;
296
- }
297
- if (this.actPanel) {
298
- this.actPanel.end();
299
- this.actPanel.$div.remove();
300
- this.actPanel = null;
301
- }
302
- if (this.project) {
303
- this.project.end();
304
- this.project = null;
305
- }
306
- if (this.activeMediaBag)
307
- this.activeMediaBag.removeAll();
308
- return result || Promise.resolve(true);
309
- }
310
-
311
- /**
312
- * Creates and initializes the {@link module:Reporter.Reporter Reporter} member
313
- * @returns {external:Promise}
314
- */
315
- initReporter() {
316
- if (this.reporter) {
317
- this.reporter.end();
318
- this.reporter = null;
319
- }
320
- this.reporter = _report_Reporter_js__WEBPACK_IMPORTED_MODULE_12__["default"].getReporter(null, this);
321
- return this.reporter.init();
322
- }
323
-
324
- /**
325
- * Creates and initializes objects of type {@link module:AWT.Timer}
326
- */
327
- initTimers() {
328
- // Main timer
329
- if (this.timer)
330
- this.timer.stop();
331
- this.timer = new _AWT_js__WEBPACK_IMPORTED_MODULE_4__/* .Timer */ .M4(() => {
332
- this.incCounterValue('time');
333
- if (this.actPanel && this.actPanel.act.maxTime > 0
334
- && this.actPanel.playing
335
- && this.counterVal['time'] >= this.actPanel.act.maxTime)
336
- this.actPanel.finishActivity(false);
337
- }, 1000, false);
338
-
339
- // One-time timer, for delayed actions
340
- if (this.delayedTimer)
341
- this.delayedTimer.stop();
342
- this.delayedTimer = new _AWT_js__WEBPACK_IMPORTED_MODULE_4__/* .Timer */ .M4(() => {
343
- if (this.delayedAction)
344
- this.delayedAction.processEvent(this.delayedAction, null);
345
- }, 1000, false);
346
- this.delayedTimer.repeats = false;
347
- }
348
-
349
- /**
350
- * Opens the reports dialog
351
- */
352
- showReports() {
353
- if (this.skin) this.skin.showReports(this.reporter);
354
- }
355
-
356
- /**
357
- * Closes the help dialog window
358
- */
359
- closeHelpWindow() {
360
- if (this.skin) this.skin._closeDlg(false);
361
- }
362
-
363
- /**
364
- * Sets the current skin
365
- * @param {module:skins/Skin.Skin} [newSkin] - The skin to use. When `null`, `defaultSkin` will be used.
366
- */
367
- setSkin(newSkin) {
368
- newSkin = newSkin || (this.project && this.project.skin ? this.project.skin : this.defaultSkin);
369
- if (newSkin && (this.skin === null || newSkin.name !== this.skin.name)) {
370
- newSkin.attach(this);
371
- this.skin = newSkin;
372
- this.skin.doLayout();
373
- }
374
- }
375
-
376
- /**
377
- * Sets the current project of this player, without starting any activity
378
- * @param {module:project/JClicProject.JClicProject} project - The project to be set
379
- */
380
- setProject(project) {
381
- if (this.project) {
382
- if (this.project !== project)
383
- this.project.end();
384
- this.removeActivity();
385
- }
386
- this.project = project || new _project_JClicProject_js__WEBPACK_IMPORTED_MODULE_9__["default"]();
387
- this.project.realize(this);
388
- }
389
-
390
- /**
391
- * Loads the specified project and starts playing at the specified activity or sequence tag.
392
- * @param {string|JClicProject} [project] - The project to load (if it's a string) or to use (if it's an object of type {@link module:project/JClicProject.JClicProject JClicProject}).
393
- * When it's a `string`, it can be the absolute or relative path to:
394
- * - A `.jclic` project file, in XML format
395
- * - A `.jclic.json` project file in JSON format
396
- * - A `.jclic.zip` compressed project file (containing one file of type '.jclic' or '.jclic.json')
397
- * - A `.scorm.zip` file, as exported by JClic Author.
398
- * - A `project.json` file, as exported by JClic Author
399
- * When `null` or `undefined`, refers to the current project.
400
- * @param {string|number} [sequence] - Sequence tag or numeric order in the {@link module:bags/ActivitySequence.ActivitySequence ActivitySequence}
401
- * to be loaded. If _sequence_ and _activity_ are both `null`, the first {@link module:bags/ActivitySequenceElement.ActivitySequenceElement ActivitySequenceElement}
402
- * will be loaded.
403
- * @param {string} [activity] - Name of the activity to be loaded (usually `null`)
404
- */
405
- load(project, sequence, activity) {
406
-
407
- this.forceFinishActivity();
408
- this.setWaitCursor(true);
409
-
410
- // The ActivityPanel object to be obtained as a result of the loading process
411
- let actp = null;
412
-
413
- // step one: load the project
414
- if (project) {
415
- if (typeof project === 'string') {
416
-
417
- // Param `project` is a file name or URL (otherwise, is a realized `JClicProject` object)
418
- const fullPath = (0,_Utils_js__WEBPACK_IMPORTED_MODULE_3__/* .getPath */ .Yn)(this.basePath, project);
419
-
420
- // Previous step: Check if `project` points to a "project.json" file
421
- if (fullPath.endsWith('project.json')) {
422
- (0,_Utils_js__WEBPACK_IMPORTED_MODULE_3__/* .log */ .Rm)('info', `Loading JSON info from: ${fullPath}`);
423
- jquery__WEBPACK_IMPORTED_MODULE_0___default().getJSON(fullPath).done(({ mainFile }) => {
424
- // Read the `mainFile` field of `project.json`
425
- if (mainFile && (0,_Utils_js__WEBPACK_IMPORTED_MODULE_3__/* .endsWith */ .d5)(mainFile, '.jclic') || (0,_Utils_js__WEBPACK_IMPORTED_MODULE_3__/* .endsWith */ .d5)(mainFile, '.jclic.json')) {
426
- // Load project's main file
427
- this.load((0,_Utils_js__WEBPACK_IMPORTED_MODULE_3__/* .getPath */ .Yn)((0,_Utils_js__WEBPACK_IMPORTED_MODULE_3__/* .getBasePath */ .DT)(fullPath), mainFile), sequence, activity);
428
- } else {
429
- (0,_Utils_js__WEBPACK_IMPORTED_MODULE_3__/* .log */ .Rm)('error', `Invalid or null "mainFile" specified in ${fullPath} - "project.json".`);
430
- }
431
- }).fail((jqhxr, textStatus, error) => {
432
- const errMsg = `${textStatus} (${error}) while loading ${project}`;
433
- (0,_Utils_js__WEBPACK_IMPORTED_MODULE_3__/* .log */ .Rm)(errMsg);
434
- window.alert(`Error!\n${errMsg}`);
435
- }).always(
436
- () => this.setWaitCursor(false)
437
- );
438
- return;
439
- }
440
-
441
- // Step 0: Check if `project` points to a ZIP file
442
- if (fullPath.endsWith('.zip')) {
443
- // TODO: Implement register of zip files in PlayerHistory
444
- this.zip = null;
445
- (0,_Utils_js__WEBPACK_IMPORTED_MODULE_3__/* .log */ .Rm)('info', `Loading ZIP file: ${fullPath}`);
446
-
447
- // Launch loading of ZIP file in a separated thread
448
- jszip_utils__WEBPACK_IMPORTED_MODULE_2___default().getBinaryContent(fullPath, (err, data) => {
449
- if (err) {
450
- this.setWaitCursor(false);
451
- (0,_Utils_js__WEBPACK_IMPORTED_MODULE_3__/* .log */ .Rm)('error', `Error loading ZIP file: ${err.toString()}`);
452
- return;
453
- }
454
- new (jszip__WEBPACK_IMPORTED_MODULE_1___default())().loadAsync(data).then(zip => {
455
- this.zip = zip;
456
- this.zip.fullZipPath = fullPath;
457
- this.zip.zipBasePath = (0,_Utils_js__WEBPACK_IMPORTED_MODULE_3__/* .getBasePath */ .DT)(fullPath);
458
- let fileName = null;
459
- // Check if ZIP contains a "project.json" file (as in the ".scorm.zip" files generated by JClic Author)
460
- if (this.zip.files['project.json']) {
461
- this.zip.files['project.json'].async('string').then(content => {
462
- try {
463
- const json = JSON.parse(content);
464
- // Read the `mainFile` field of `project.json`
465
- if ((0,_Utils_js__WEBPACK_IMPORTED_MODULE_3__/* .endsWith */ .d5)(json['mainFile'], '.jclic')) {
466
- // Load project's main file
467
- this.load((0,_Utils_js__WEBPACK_IMPORTED_MODULE_3__/* .getPath */ .Yn)(this.zip.zipBasePath, json['mainFile']), sequence, activity);
468
- } else {
469
- (0,_Utils_js__WEBPACK_IMPORTED_MODULE_3__/* .log */ .Rm)('error', `Invalid or null "mainFile" specified in ${fullPath} - "project.json".`);
470
- }
471
- } catch (err) {
472
- (0,_Utils_js__WEBPACK_IMPORTED_MODULE_3__/* .log */ .Rm)('error', `Error reading "project.json" in ${fullPath}: ${err ? err.toString() : 'unknown error'}`);
473
- }
474
- }).catch(reason => {
475
- (0,_Utils_js__WEBPACK_IMPORTED_MODULE_3__/* .log */ .Rm)('error', `Error reading ZIP file: ${reason ? reason.toString() : 'unknown reason'}`);
476
- });
477
- } else {
478
- // Find first file with extension '.jclic' inside the zip file
479
- fileName = Object.keys(this.zip.files).find(fn => fn.endsWith('.jclic')) || null;
480
- if (fileName)
481
- this.load((0,_Utils_js__WEBPACK_IMPORTED_MODULE_3__/* .getPath */ .Yn)(this.zip.zipBasePath, fileName), sequence, activity);
482
- else
483
- (0,_Utils_js__WEBPACK_IMPORTED_MODULE_3__/* .log */ .Rm)('error', 'This ZIP file does not contain any JClic project!');
484
- }
485
- this.setWaitCursor(false);
486
- }).catch(reason => {
487
- (0,_Utils_js__WEBPACK_IMPORTED_MODULE_3__/* .log */ .Rm)('error', `Error reading ZIP file: ${reason ? reason.toString() : 'unknown reason'}`);
488
- this.setWaitCursor(false);
489
- });
490
- });
491
- return;
492
- } else if (this.localFS && window.JClicObject && !window.JClicObject.projectFiles[fullPath]) {
493
- const scriptTag = document.createElement('script');
494
- scriptTag.src = `${fullPath}.js`;
495
- scriptTag.onload = () => {
496
- // 25 Mar 20201:
497
- // Workaround for a bug on Chrome and Firefox XML parsers, throwing errors whith hexadecimal character entities
498
- if (window.JClicObject.projectFiles[fullPath]) {
499
- window.JClicObject.projectFiles[fullPath] = (0,_Utils_js__WEBPACK_IMPORTED_MODULE_3__/* .mReplace */ .wF)([
500
- [/&#xD;/g, '\r'],
501
- [/&#xA;/g, '\n'],
502
- [/&#x9;/g, '\t'],
503
- ], window.JClicObject.projectFiles[fullPath]);
504
- this.load(project, sequence, activity);
505
- }
506
- };
507
- document.head.appendChild(scriptTag);
508
- this.setWaitCursor(false);
509
- return;
510
- }
511
-
512
- // Step one: load the project file
513
- const processProjectFile = fp => {
514
- const isXml = fp.indexOf('data:text/xml;') === 0 || fp.endsWith('.jclic');
515
-
516
- const loader = isXml ? jquery__WEBPACK_IMPORTED_MODULE_0___default().get(fp, null, null, 'xml') : jquery__WEBPACK_IMPORTED_MODULE_0___default().getJSON(fp);
517
-
518
- loader.done(data => {
519
- if (data === null || typeof data !== 'object') {
520
- (0,_Utils_js__WEBPACK_IMPORTED_MODULE_3__/* .log */ .Rm)('error', `Bad data. Project not loaded: ${project}`);
521
- return;
522
- }
523
- const prj = new _project_JClicProject_js__WEBPACK_IMPORTED_MODULE_9__["default"]();
524
- if (isXml)
525
- prj.setProperties(jquery__WEBPACK_IMPORTED_MODULE_0___default()(data).find('JClicProject'), fullPath, this.zip, this.options);
526
- else
527
- prj.setAttributes(data, fullPath, this.zip, this.options);
528
-
529
- (0,_Utils_js__WEBPACK_IMPORTED_MODULE_3__/* .log */ .Rm)('info', `Project file loaded and parsed: ${project}`);
530
- const elements = prj.mediaBag.buildAll(null, element => {
531
- (0,_Utils_js__WEBPACK_IMPORTED_MODULE_3__/* .log */ .Rm)('trace', `"${element.name}" ready.`);
532
- this.incProgress(1);
533
- }, this);
534
- (0,_Utils_js__WEBPACK_IMPORTED_MODULE_3__/* .log */ .Rm)('info', `Media elements to be loaded: ${elements}`);
535
- this.setProgress(0, elements);
536
- let loops = 0;
537
- const interval = 500;
538
- this.setWaitCursor(true);
539
- const checkMedia = window.setInterval(() => {
540
- // Wait for a maximum time of two minutes
541
- if (++loops > this.options.maxWaitTime / interval) {
542
- window.clearInterval(checkMedia);
543
- this.setProgress(-1);
544
- this.setWaitCursor(false);
545
- (0,_Utils_js__WEBPACK_IMPORTED_MODULE_3__/* .log */ .Rm)('error', 'Error loading media');
546
- }
547
- const waitingObjects = prj.mediaBag.countWaitingElements();
548
- // player.setProgress(waiting)
549
- if (waitingObjects === -1) {
550
- window.clearInterval(checkMedia);
551
- this.setProgress(-1);
552
- this.setWaitCursor(false);
553
- // Call `load` again, passing the loaded [JClicProject](JClicProject.html) as a parameter
554
- this.load(prj, sequence, activity);
555
- }
556
- }, interval);
557
- }).fail((jqXHR, textStatus, errorThrown) => {
558
- const errMsg = `${textStatus} (${errorThrown}) while loading ${project}`;
559
- (0,_Utils_js__WEBPACK_IMPORTED_MODULE_3__/* .log */ .Rm)(errMsg);
560
- window.alert(`Error!\n${errMsg}`);
561
- }).always(() => this.setWaitCursor(false));
562
- };
563
-
564
-
565
- (0,_Utils_js__WEBPACK_IMPORTED_MODULE_3__/* .log */ .Rm)('info', `Loading project: ${project}`);
566
- let fp = fullPath;
567
-
568
- // Special case for ZIP files
569
- if (this.zip) {
570
- const fName = (0,_Utils_js__WEBPACK_IMPORTED_MODULE_3__/* .getRelativePath */ .Aj)(fp, this.zip.zipBasePath);
571
- if (this.zip.files[fName]) {
572
- this.zip.file(fName).async('string').then(text => {
573
- processProjectFile(`data:${fName.endsWith('.jclic') ? 'text/xml' : 'application/json'};charset=UTF-8,${text}`);
574
- }).catch(reason => {
575
- (0,_Utils_js__WEBPACK_IMPORTED_MODULE_3__/* .log */ .Rm)('error', `Unable to extract "${fName}" from ZIP file because of: ${reason ? reason.toString() : 'unknown reason'}`);
576
- this.setWaitCursor(false);
577
- });
578
- return;
579
- }
580
- }
581
- // Special case for local file systems (using `file` protocol)
582
- else if (this.localFS) {
583
- // Check if file is already loaded in the global variable `JClicObject`
584
- if (window.JClicObject && window.JClicObject.projectFiles[fullPath]) {
585
- fp = `data:${fullPath.endsWith('.jclic') ? 'text/xml' : 'application/json'};charset=UTF-8,${window.JClicObject.projectFiles[fullPath]}`;
586
- } else {
587
- (0,_Utils_js__WEBPACK_IMPORTED_MODULE_3__/* .log */ .Rm)('error', `Unable to load: ${fullPath}.js`);
588
- this.setWaitCursor(false);
589
- return;
590
- }
591
- }
592
- processProjectFile(fp);
593
- return;
594
- }
595
-
596
- // From here, assume that `project` is a [JClicProject](JClicProject.html)
597
- this.setProject(project);
598
-
599
- // If none specified, start with the first element of the sequence
600
- if (!sequence && !activity)
601
- sequence = '0';
602
-
603
- // start reporter session
604
- if (this.reporter)
605
- this.reporter.newSession(project);
606
-
607
- }
608
-
609
- // Step two: load the ActivitySequenceElement
610
- if (!(0,_Utils_js__WEBPACK_IMPORTED_MODULE_3__/* .isNullOrUndef */ .Pj)(sequence)) {
611
- (0,_Utils_js__WEBPACK_IMPORTED_MODULE_3__/* .log */ .Rm)('info', `Loading sequence: ${sequence}`);
612
- this.navButtonsDisabled = false;
613
- // Try to load sequence by tag
614
- let ase = null;
615
- if (typeof sequence === 'string')
616
- ase = this.project.activitySequence.getElementByTag(sequence, true);
617
- if (ase === null) {
618
- // Try to treat 'sequence' as a number
619
- const n = parseInt(sequence, 10);
620
- if (typeof n === 'number')
621
- ase = this.project.activitySequence.getElement(n, true);
622
- }
623
-
624
- if (ase !== null) {
625
- // Success! We have a real [ActivitySequenceElement](ActivitySequenceElement.html)
626
- if (this.reporter)
627
- this.reporter.newSequence(ase);
628
- activity = ase.activity;
629
- }
630
- }
631
-
632
- // Step three: load the activity
633
- if (activity) {
634
- const act = this.project.getActivity(activity);
635
- if (act) {
636
- // Success! We have a real [Activity](Activity.html)
637
- (0,_Utils_js__WEBPACK_IMPORTED_MODULE_3__/* .log */ .Rm)('info', `Loading activity: ${activity}`);
638
- // Clean static references to previous audio elements
639
- _bags_MediaBagElement_js__WEBPACK_IMPORTED_MODULE_13__["default"].resetAudioElements();
640
- act.prepareMedia(this);
641
- this.project.activitySequence.checkCurrentActivity(act.name);
642
- actp = act.getActivityPanel(this);
643
- actp.buildVisualComponents();
644
- } else {
645
- (0,_Utils_js__WEBPACK_IMPORTED_MODULE_3__/* .log */ .Rm)('error', `Missing activity: ${activity}`);
646
- }
647
- }
648
-
649
- // Step four: put the activity panel on place
650
-
651
- // Remove the current ActivityPanel
652
- if (this.actPanel !== null) {
653
- this.actPanel.end();
654
- this.actPanel.$div.remove();
655
- this.actPanel = null;
656
- this.setCounterValue('time', 0);
657
- }
658
-
659
- // Attach the new ActivityPanel
660
- if (actp) {
661
- // Sets the actPanel member to this ActivityPanel
662
- this.actPanel = actp;
663
-
664
- if (this.options.fade > 0)
665
- this.actPanel.$div.css('display', 'none');
666
-
667
- // Places the JQuery DOM element of actPanel within the player main panel
668
- this.$div.prepend(this.actPanel.$div);
669
- if (this.skin)
670
- this.skin.resetAllCounters(false);
671
-
672
- // Sets the current skin
673
- if (this.actPanel.skin)
674
- this.setSkin(this.actPanel.skin);
675
- else if (this.project.skin) {
676
- this.setSkin(this.project.skin);
677
- this.lastProjectSkin = this.project.skin;
678
- }
679
- else if (this.lastProjectSkin)
680
- this.setSkin(this.lastProjectSkin);
681
- else
682
- this.setSkin(null);
683
-
684
- if (this.skin) {
685
- // Enable or disable actions
686
- const hasReturn = this.history.storedElementsCount() > 0 || this.options.returnAsExit;
687
- const navBtnFlag = this.navButtonsAlways ?
688
- 'both' : this.navButtonsDisabled ?
689
- 'none' : this.project.activitySequence.getNavButtonsFlag();
690
- this.actions['next'].setEnabled((navBtnFlag === 'fwd' || navBtnFlag === 'both') &&
691
- this.project.activitySequence.hasNextAct(hasReturn));
692
- this.actions['prev'].setEnabled((navBtnFlag === 'back' || navBtnFlag === 'both') &&
693
- this.project.activitySequence.hasPrevAct(hasReturn));
694
- this.actions['return'].setEnabled(hasReturn);
695
- this.actions['help'].setEnabled(this.actPanel.act.helpWindowAllowed());
696
- this.actions['reset'].setEnabled(this.actPanel.act.canReinit());
697
- this.actions['info'].setEnabled(this.actPanel.act.hasInfo());
698
- }
699
- this.doLayout();
700
- this.initActivity();
701
-
702
- this.history.pushBrowserHistory();
703
-
704
- this.actPanel.$div.fadeIn(this.options.fade, () => this.activityReady());
705
- }
706
- this.setWaitCursor(false);
707
- }
708
-
709
- /**
710
- * Forces the current activity to stop playing.
711
- */
712
- forceFinishActivity() {
713
- this.timer.stop();
714
- this.delayedTimer.stop();
715
- if (this.actPanel) {
716
- this.closeHelpWindow();
717
- this.actPanel.forceFinishActivity();
718
- this.stopMedia();
719
- this.activeMediaBag.removeAll();
720
- }
721
- }
722
-
723
- /**
724
- *
725
- * Removes the current {@link module:Activity.ActivityPanel ActivityPanel} from this player
726
- */
727
- removeActivity() {
728
- this.forceFinishActivity();
729
- if (this.actPanel) {
730
- this.actPanel.end();
731
- this.actPanel.$div.remove();
732
- this.actPanel = null;
733
- this.setMsg(null);
734
- this.doLayout();
735
- }
736
- }
737
-
738
- /**
739
- *
740
- * Initializes the activity
741
- */
742
- initActivity() {
743
- this.setWaitCursor(true);
744
- this.timer.stop();
745
- this.delayedTimer.stop();
746
- this.setCounterValue('time', 0);
747
- this.stopMedia();
748
- if (this.actPanel) {
749
- this.actPanel.initActivity();
750
- this.timer.start();
751
- if (!this.actPanel.act.mustPauseSequence())
752
- this.startAutoPassTimer();
753
- (0,_Utils_js__WEBPACK_IMPORTED_MODULE_3__/* .log */ .Rm)('info', `Activity "${this.actPanel.act.name}" running`);
754
- }
755
- this.setWaitCursor(false);
756
- }
757
-
758
- /**
759
- * Called by {@link module:JClicPlayer.JClicPlayer#load} when the {@link module:Activity.ActivityPanel ActivityPanel} is fully visible, just
760
- * after the JQuery animation effect.
761
- */
762
- activityReady() {
763
- if (this.actPanel) {
764
- this.actPanel.activityReady();
765
- (0,_Utils_js__WEBPACK_IMPORTED_MODULE_3__/* .log */ .Rm)('info', 'Activity ready');
766
- }
767
- }
768
-
769
- /**
770
- * Starts the activity. This method is usually called from text activities with previous text.
771
- */
772
- startActivity() {
773
- this.setWaitCursor(true);
774
- if (this.actPanel)
775
- this.actPanel.startActivity();
776
- this.setWaitCursor(false);
777
- }
778
-
779
- /**
780
- * Configures the layout and visual aspect of the player area.
781
- */
782
- doLayout() {
783
-
784
- // Main player area settings
785
- const
786
- width = this.dim.width = this.$div.width(),
787
- height = this.dim.height = this.$div.height(),
788
- mainCss = {
789
- 'background-color': this.actPanel ? this.actPanel.act.bgColor : 'azure',
790
- 'background-image': ''
791
- };
792
-
793
- if (this.actPanel) {
794
- const act = this.actPanel.act;
795
- if (act.bgGradient)
796
- // Canvas version also available
797
- mainCss['background-image'] = act.bgGradient.getCss();
798
-
799
- if (act.bgImageFile && act.bgImageFile.length > 0) {
800
- this.project.mediaBag.getElement(act.bgImageFile, true).getFullPathPromise().then(bgImageUrl => {
801
- this.$div.css({
802
- 'background-image': 'url(\'' + bgImageUrl + '\')',
803
- 'background-repeat': act.tiledBgImg ? 'repeat' : 'no-repeat',
804
- 'background-position': act.tiledBgImg ? '' : 'center center'
805
- });
806
- });
807
- }
808
-
809
- // Activity panel settings
810
- // Calc the maximum rectangle available for the activity panel
811
- const
812
- m = _Utils_js__WEBPACK_IMPORTED_MODULE_3__/* .settings */ .W0.BoxBase.AC_MARGIN,
813
- proposedRect = new _AWT_js__WEBPACK_IMPORTED_MODULE_4__/* .Rectangle */ .M_(m, m, width - 2 * m, height - 2 * m);
814
-
815
- if (this.actPanel.bgImage && !act.tiledBgImg && act.absolutePositioned) {
816
- // Special case: when the activity has a background image not tiled, and an absolute
817
- // position has been specified, the ActivityPanel must be placed at this absolute
818
- // position, relative to the background image
819
- this.bgImageOrigin.x = (width - this.actPanel.bgImage.width) / 2;
820
- this.bgImageOrigin.y = (height - this.actPanel.bgImage.height) / 2;
821
- proposedRect.pos.moveTo(this.bgImageOrigin);
822
- proposedRect.dim.width -= this.bgImageOrigin.x - m;
823
- proposedRect.dim.height -= this.bgImageOrigin.y - m;
824
- proposedRect.dim.width = Math.min(proposedRect.dim.width, width);
825
- proposedRect.dim.height = Math.min(proposedRect.dim.height, height);
826
- }
827
-
828
- // ActivityPanel will calculate and set its position and size based on the maximum and optimal
829
- // available space
830
- /* TODO: Try with a computed rectangle instead of "this", to avoid the loss of the right margin
831
- * in narrow displays */
832
- this.actPanel.fitTo(proposedRect, this);
833
- }
834
- this.$div.css(mainCss);
835
- }
836
-
837
- /**
838
- * Plays the specified media.
839
- * @param {module:media/MediaContent.MediaContent} mediaContent - The media to be played
840
- * @param {module:boxes/ActiveBox.ActiveBox} [mediaPlacement] - The cell where the graphic component of this media should be placed (used with video objects)
841
- * @param {function[]} [delayedActions] - If set, store the the action in this array for future execution
842
- */
843
- playMedia(mediaContent, mediaPlacement = null, delayedActions = null) {
844
-
845
- let ji = null;
846
- const fn = mediaContent.file;
847
- let action = null;
848
-
849
- switch (mediaContent.type) {
850
- case 'PLAY_AUDIO':
851
- case 'PLAY_VIDEO':
852
- case 'PLAY_MIDI':
853
- case 'RECORD_AUDIO':
854
- case 'PLAY_RECORDED_AUDIO':
855
- if (this.audioEnabled) {
856
- const amp = this.activeMediaBag.getActiveMediaPlayer(mediaContent, this.project.mediaBag, this);
857
- if (amp)
858
- action = () => amp.play(mediaPlacement);
859
- }
860
- break;
861
-
862
- case 'RUN_CLIC_PACKAGE':
863
- ji = new _bags_JumpInfo_js__WEBPACK_IMPORTED_MODULE_10__["default"]('JUMP', fn);
864
- if (mediaContent.externalParam) {
865
- // Relative path computed in History.processJump
866
- ji.projectPath = mediaContent.externalParam;
867
- }
868
- action = () => this.history.processJump(ji, true);
869
- break;
870
-
871
- case 'RUN_CLIC_ACTIVITY':
872
- this.history.push();
873
- action = () => this.load(null, null, fn);
874
- break;
875
-
876
- case 'RETURN':
877
- if (this.history.storedElementsCount() > 0 || !this.options.returnAsExit) {
878
- action = () => this.history.pop();
879
- break;
880
- }
881
- case 'EXIT':
882
- ji = new _bags_JumpInfo_js__WEBPACK_IMPORTED_MODULE_10__["default"]('EXIT', fn);
883
- action = () => this.history.processJump(ji, false);
884
- break;
885
-
886
- case 'RUN_EXTERNAL':
887
- action = () => this.runCmd(fn);
888
- break;
889
-
890
- case 'URL':
891
- if (fn)
892
- // When mediaContent.level is 2 or more, the URL will be opened in a separate window.
893
- action = () => this.displayURL(fn, mediaContent.level > 1);
894
- break;
895
-
896
- default:
897
- (0,_Utils_js__WEBPACK_IMPORTED_MODULE_3__/* .log */ .Rm)('error', `Unknown media type: ${mediaContent.type}`);
898
- break;
899
- }
900
-
901
- // Execute the action or pass callback
902
- if (delayedActions && action)
903
- delayedActions.push(action);
904
- else if (action)
905
- action();
906
- }
907
-
908
- /**
909
- * Stops currently playing media
910
- * @param {number} [level=-1] - Sets the threshold above which all media objects with equal
911
- * or greater `level` will also also be muted.
912
- */
913
- stopMedia(level) {
914
- if (typeof level !== 'number')
915
- level = -1;
916
- this.activeMediaBag.stopAll(level);
917
- }
918
-
919
- /**
920
- * Launches the specified system command.
921
- * Currently not implemented.
922
- * @param {string} cmd
923
- */
924
- runCmd(cmd) {
925
- (0,_Utils_js__WEBPACK_IMPORTED_MODULE_3__/* .log */ .Rm)('warn', `Unsupported call to external command: "${cmd}"`);
926
- }
927
-
928
- /**
929
- * Called from {@link module:Activity.Activity Activity} when finished.
930
- * @param {boolean} _completedOK - `true` when the activity was successfully completed, `false`
931
- * otherwise.
932
- */
933
- activityFinished(_completedOK) {
934
- this.closeHelpWindow();
935
- (0,_Utils_js__WEBPACK_IMPORTED_MODULE_3__/* .log */ .Rm)('info', 'Activity finished');
936
- this.timer.stop();
937
- this.startAutoPassTimer();
938
- }
939
-
940
- /**
941
- * Starts the automatic jump to next activity, when applicable.
942
- */
943
- startAutoPassTimer() {
944
- const ase = this.project.activitySequence.getCurrentAct();
945
- if (ase !== null && ase.delay > 0 && !this.delayedTimer.isRunning() && !this.navButtonsDisabled) {
946
- this.delayedAction = this.actions['next'];
947
- this.delayedTimer.interval = ase.delay * 1000;
948
- this.delayedTimer.start();
949
- }
950
- }
951
-
952
- /**
953
- *
954
- * Sets the current main message.
955
- * @param {module:boxes/ActiveBoxContent.ActiveBoxContent} abc - The content of the message
956
- */
957
- setMsg(abc) {
958
- const ab = this.skin ? this.skin.getMsgBox() : null;
959
- if (ab) {
960
- ab.clear();
961
- this.skin.invalidate(ab).update();
962
- ab.setContent(abc ? abc : _boxes_ActiveBoxContent_js__WEBPACK_IMPORTED_MODULE_11__["default"].EMPTY_CONTENT);
963
- // TODO: Move this method to Skin
964
- this.skin.invalidate(ab).update();
965
- ab.playMedia(this);
966
- }
967
- }
968
-
969
- /**
970
- * Launches the active media content associated to the main message, if any.
971
- */
972
- playMsg() {
973
- if (this.skin && this.skin.getMsgBox())
974
- this.skin.getMsgBox().playMedia(this);
975
- }
976
-
977
- /**
978
- * Sets a value to the specified counter
979
- * @param {string} counter - The id of the counter ('score', 'actions' or 'time')
980
- * @param {number} newValue - The value to be set
981
- */
982
- setCounterValue(counter, newValue) {
983
- this.counterVal[counter] = newValue;
984
- if (this.skin && this.skin.counters[counter])
985
- this.skin.counters[counter].setValue(newValue);
986
- }
987
-
988
- /**
989
- * Gets the current value for the specified counter
990
- * @param {string} counter - The id of the counter ('score', 'actions' or 'time')
991
- * @returns {number}
992
- */
993
- getCounterValue(counter) {
994
- return this.counterVal[counter];
995
- }
996
-
997
- /**
998
- * Enables or disables a specific counter
999
- * @param {string} counter - The id of the counter ('score', 'actions' or 'time')
1000
- * @param {boolean} bEnabled - When `true`, the counter will be enabled.
1001
- */
1002
- setCounterEnabled(counter, bEnabled) {
1003
- if (this.skin) {
1004
- this.skin.enableCounter(counter, bEnabled);
1005
- this.setCountDown(counter, 0);
1006
- }
1007
- }
1008
-
1009
- /**
1010
- * Increments by 1 the value of the specified counter
1011
- * @param {string} counter - The id of the counter ('score', 'actions' or 'time')
1012
- */
1013
- incCounterValue(counter) {
1014
- this.counterVal[counter]++;
1015
-
1016
- const
1017
- actp = this.actPanel,
1018
- cnt = this.skin ? this.skin.counters[counter] : null;
1019
-
1020
- if (cnt)
1021
- cnt.setValue(this.counterVal[counter]);
1022
- if (counter === 'actions' && actp !== null && actp.act.maxActions > 0 && actp.playing && this.counterVal['actions'] >= actp.act.maxActions)
1023
- window.setTimeout(() => { actp.finishActivity(actp.solved); }, 0);
1024
- }
1025
-
1026
- /**
1027
- * Sets the specified counter in count-down status, starting at `maxValue`.
1028
- * @param {string} counter - The id of the counter ('score', 'actions' or 'time')
1029
- * @param {number} maxValue - The value from which to start counting down
1030
- */
1031
- setCountDown(counter, maxValue) {
1032
- //this.counterVal[counter] = maxValue
1033
- if (this.skin && this.skin.counters[counter])
1034
- this.skin.counters[counter].setCountDown(maxValue);
1035
- }
1036
-
1037
- /**
1038
- * Set/unset the panel in 'wait' state
1039
- * @param {boolean} status
1040
- */
1041
- setWaitCursor(status) {
1042
- if (this.skin)
1043
- this.skin.setWaitCursor(status);
1044
- }
1045
-
1046
- /**
1047
- * Sets the current value of the progress bar
1048
- * @param {number} val - The current value. Should be less or equal than `max`. When -1, the progress bar will be hidden.
1049
- * @param {number} [max] - Optional parameter representing the maximum value. When passed, the progress bar will be displayed.
1050
- */
1051
- setProgress(val, max) {
1052
- if (this.skin)
1053
- this.skin.setProgress(val, max);
1054
- }
1055
-
1056
- /**
1057
- * Increments the progress bar value by the specified amount, only when the progress bar is running.
1058
- * @param {number} [val=1] - The amount to increment. When not defined, it's 1.
1059
- */
1060
- incProgress(val = 1) {
1061
- if (this.skin)
1062
- this.skin.incProgress(val);
1063
- }
1064
-
1065
- /**
1066
- * Builds an {@link module:media/ActiveMediaPlayer.ActiveMediaPlayer ActiveMediaPlayer} for the specified {@link module:media/MediaContent.MediaContent}
1067
- * @param {module:media/MediaContent.MediaContent} mediaContent - The media content to be played
1068
- * @returns {module:media/ActiveMediaPlayer.ActiveMediaPlayer}
1069
- */
1070
- getActiveMediaPlayer(mediaContent) {
1071
- return this.activeMediaBag && mediaContent ? this.activeMediaBag.getActiveMediaPlayer(mediaContent, this.project.mediaBag, this) : null;
1072
- }
1073
-
1074
- /**
1075
- * Notifies the reporting system that a new activity has started
1076
- * @param {module:Activity.Activity} act - The activity that is sending the notification
1077
- */
1078
- reportNewActivity(act) {
1079
- const ase = this.project.activitySequence.getCurrentAct();
1080
- if (this.reporter) {
1081
- if (ase.tag === this.reporter.getCurrentSequenceTag())
1082
- // Notify that the sequence has changed
1083
- this.reporter.newSequence(ase);
1084
- if (act.includeInReports)
1085
- this.reporter.newActivity(act);
1086
- }
1087
- this.setCounterValue('actions', 0);
1088
- this.setCounterValue('score', 0);
1089
- }
1090
-
1091
- /**
1092
- * Notifies the reporting system that a new action has been performed on the current activity
1093
- * @param {module:Activity.Activity} act - The activity that is sending the notification
1094
- * @param {string} type - Type of action (match, move, switch...)
1095
- * @param {string} source - Object acting as a source of the action (cell, grid, clue...)
1096
- * @param {string} dest - When applicable, object acting as a receiver of the action (cell, grid...)
1097
- * @param {boolean} ok - Whether the action was OK or not
1098
- * @param {number} currentScore - The current score of the activity
1099
- */
1100
- reportNewAction(act, type, source, dest, ok, currentScore) {
1101
- if (this.reporter && act.includeInReports && act.reportActions)
1102
- this.reporter.newAction(type, source, dest, ok);
1103
- if (currentScore >= 0) {
1104
- this.incCounterValue('actions');
1105
- this.setCounterValue('score', currentScore);
1106
- }
1107
- }
1108
-
1109
- /**
1110
- * Notifies the reporting system that the current activity has finished
1111
- * @param {module:Activity.Activity} act - The activity that is sending the notification
1112
- * @param {boolean} solved - Whether the activity was successfully completed or not.
1113
- */
1114
- reportEndActivity(act, solved) {
1115
- if (this.reporter && act.includeInReports)
1116
- this.reporter.endActivity(this.counterVal['score'], this.counterVal['actions'], solved);
1117
- }
1118
-
1119
- /**
1120
- * Shows the help info provided by the activity
1121
- * @param {external:jQuery} $hlpComponent - The jQuery DOM component to be shown.
1122
- * @returns {boolean} - True when the component was successfully displayed
1123
- */
1124
- showHelp($hlpComponent) {
1125
- return this.skin ? this.skin.showHelp($hlpComponent) : false;
1126
- }
1127
-
1128
- /**
1129
- * Navigates to the requested URL
1130
- * @param {string} url - The URL to navigate to
1131
- * @param {boolean} inFrame - When `true` opens in a new frame
1132
- */
1133
- displayURL(url, inFrame) {
1134
- if (url) {
1135
- if (inFrame)
1136
- window.open(url, this.options.infoUrlFrame);
1137
- else {
1138
- this.end().then(() => { window.location.href = url; });
1139
- }
1140
- }
1141
- }
1142
-
1143
- /**
1144
- * Only when `exitUrl` has been specified in `options`, navigates to the specified URL
1145
- * @param {string} url - The URL to navigate to.
1146
- */
1147
- exit(url) {
1148
- this.displayURL(url || this.options.exitUrl, false);
1149
- }
1150
-
1151
- /**
1152
- * Sets a title in a specific HTML element, if provided.
1153
- * @param {string} docTitle
1154
- */
1155
- setWindowTitle(docTitle) {
1156
- (0,_Utils_js__WEBPACK_IMPORTED_MODULE_3__/* .log */ .Rm)('info', `running ${docTitle}`);
1157
- }
1158
- }
1159
-
1160
- Object.assign(JClicPlayer.prototype, {
1161
- /**
1162
- * Object with miscellaneous options.
1163
- * @name module:JClicPlayer.JClicPlayer#options
1164
- * @type {object} */
1165
- options: {
1166
- //
1167
- // Max waiting time to have all media loaded (milliseconds)
1168
- maxWaitTime: 120000,
1169
- //
1170
- // Name of the frame where to open links
1171
- infoUrlFrame: '_blank',
1172
- //
1173
- // URL where to navigate to on exit
1174
- exitUrl: null,
1175
- //
1176
- // When `true` and no elements on sequence stack, RETURN acts as EXIT
1177
- returnAsExit: false,
1178
- //
1179
- // At the beginning, the audio should be enabled or disabled
1180
- audioEnabled: true,
1181
- //
1182
- // Navigation buttons are always visible (for debugging purposes)
1183
- navButtonsAlways: false,
1184
- //
1185
- // Time (milliseconds) of the fade-in animation of the activity panel. When 0, no animation
1186
- // is performed
1187
- fade: 300,
1188
- // Minimum horizontal swipe length to be considered an activity change gesture
1189
- minSwipeX: 40,
1190
- // Maximum vertical swipe length to be considered an activity change gesture
1191
- maxSwipeY: 100,
1192
- // Read swipe gestures as in right-to-left languages (default is left-to-right)
1193
- rightToLeft: false,
1194
- },
1195
- /**
1196
- * Unique ID of this player, randomly generated by the constructor
1197
- * @name module:JClicPlayer.JClicPlayer#id
1198
- * @type {string} */
1199
- id: 'JC0000',
1200
- /**
1201
- * The JQuery "div" element used by this player as stage for activities
1202
- * @name module:JClicPlayer.JClicPlayer#$div
1203
- * @type {external:jQuery} */
1204
- $div: null,
1205
- /**
1206
- * The JQuery top container where this player will deploy
1207
- * @name module:JClicPlayer.JClicPlayer#$topDiv
1208
- * @type {external:jQuery} */
1209
- $topDiv: null,
1210
- /**
1211
- * The main container of all JClic components
1212
- * @name module:JClicPlayer.JClicPlayer#$mainContainer
1213
- * @type {external:jQuery} */
1214
- $mainContainer: null,
1215
- /**
1216
- * Flag indicatig that this player has switched to full screen at least once
1217
- * @name module:JClicPlayer.JClicPlayer#fullScreenChecked
1218
- * @type {boolean} */
1219
- fullScreenChecked: false,
1220
- /**
1221
- * The {@link module:project/JClicProject.JClicProject JClicProject} currently hosted in this player
1222
- * @name module:JClicPlayer.JClicPlayer#project
1223
- * @type {module:project/JClicProject.JClicProject} */
1224
- project: null,
1225
- /**
1226
- * Relative path or absolute URL to be used as a base to access files
1227
- * @name module:JClicPlayer.JClicPlayer#basePath
1228
- * @type {string} */
1229
- basePath: '',
1230
- /**
1231
- * A {@link external:JSZip} object pointing to a `jclic.zip` or `jclic.scorm.zip` file containing
1232
- * the current project.
1233
- * Two extra properties will be added to this object when loaded:
1234
- * - __zip.fullZipPath__ {string} - The full path of the ZIP file
1235
- * - __zip.zipBasePath__ {string} - The path to the folder containing the ZIP file
1236
- * @name module:JClicPlayer.JClicPlayer#zip
1237
- * @type {external:JSZip} */
1238
- zip: null,
1239
- /**
1240
- * This flag indicates if the player is running inside a document loaded by `file:` protocol
1241
- * @name module:JClicPlayer.JClicPlayer#localFS
1242
- * @type {boolean}
1243
- */
1244
- localFS: false,
1245
- /**
1246
- * The {@link module:Activity.ActivityPanel ActivityPanel} currently running on this player.
1247
- * @name module:JClicPlayer.JClicPlayer#actPanel
1248
- * @type {module:Activity.Activity#Panel} */
1249
- actPanel: null,
1250
- /**
1251
- * This object records the list of the activities played during the current session.
1252
- * @name module:JClicPlayer.JClicPlayer#history
1253
- * @type {module:PlayerHistory.PlayerHistory} */
1254
- history: null,
1255
- /**
1256
- * The Skin currently used by this player.
1257
- * @name module:JClicPlayer.JClicPlayer#skin
1258
- * @type {module:skins/Skin.Skin} */
1259
- skin: null,
1260
- /**
1261
- * The default Skin to be used if none specified
1262
- * @name module:JClicPlayer.JClicPlayer#defaultSkin
1263
- * @type {module:skins/Skin.Skin} */
1264
- defaultSkin: null,
1265
- /**
1266
- * The last skin directly specified by a {@link module:project/JClicProject.JClicProject JClicProject}
1267
- * @name module:JClicPlayer.JClicPlayer#defaultSkin
1268
- * @type {module:skins/Skin.Skin} */
1269
- lastProjectSkin: null,
1270
- /**
1271
- * Object containing references to realized media objects, ready to play.
1272
- * @name module:JClicPlayer.JClicPlayer#activeMediaBag
1273
- * @type {module:media/ActiveMediaBag.ActiveMediaBag} */
1274
- activeMediaBag: null,
1275
- /**
1276
- * Object responsible for passing the scores obtained by users to a external reporting systems
1277
- * when playing activities.
1278
- * @name module:JClicPlayer.JClicPlayer#reporter
1279
- * @type {module:report/Reporter.Reporter} */
1280
- reporter: null,
1281
- /**
1282
- * Collection of {@link module:AWT.Action} objects used by this player.
1283
- * @name module:JClicPlayer.JClicPlayer#actions
1284
- * @type {module:AWT.Action[]} */
1285
- actions: {},
1286
- /**
1287
- * Main timer object used to feed the time counter. Ticks every second.
1288
- * @name module:JClicPlayer.JClicPlayer#timer
1289
- * @type {module:AWT.Timer} */
1290
- timer: null,
1291
- /**
1292
- * Timer for delayed actions
1293
- * @name module:JClicPlayer.JClicPlayer#delayedTimer
1294
- * @type {module:AWT.Timer} */
1295
- delayedTimer: null,
1296
- /**
1297
- * This variable holds the action to be executed by `delayedTimer`
1298
- * @name module:JClicPlayer.JClicPlayer#delayedAction
1299
- * @type {module:AWT.Action} */
1300
- delayedAction: null,
1301
- /**
1302
- * @typedef JClicPlayer~counterValType
1303
- * @type {object}
1304
- * @property {number} score
1305
- * @property {number} actions
1306
- * @property {number} time */
1307
- /**
1308
- * Current values of the counters
1309
- * @name module:JClicPlayer.JClicPlayer#counterVal
1310
- * @type {module:JClicPlayer.JClicPlayer~counterValType} */
1311
- counterVal: { score: 0, actions: 0, time: 0 },
1312
- /**
1313
- * Point indicating the upper-left corner of the current background image
1314
- * @name module:JClicPlayer.JClicPlayer#bgImageOrigin
1315
- * @type {module:AWT.Point} */
1316
- bgImageOrigin: null,
1317
- /**
1318
- * Whether the player must play all sounds (including system sounds) and other media content
1319
- * of the activities.
1320
- * @name module:JClicPlayer.JClicPlayer#audioEnabled
1321
- * @type {boolean} */
1322
- audioEnabled: true,
1323
- /**
1324
- * Whether the navigation buttons `next` and `back` are enabled o disabled.
1325
- * @name module:JClicPlayer.JClicPlayer#navButtonsDisabled
1326
- * @type {boolean} */
1327
- navButtonsDisabled: false,
1328
- /**
1329
- * When this flag is `true`, the navigation buttons are always enabled despite
1330
- * of the indications made by the activities or the sequence control system.
1331
- * This is used only to debug projects with complicated sequence chaining.
1332
- * @name module:JClicPlayer.JClicPlayer#navButtonsAlways
1333
- * @type {boolean} */
1334
- navButtonsAlways: false,
1335
- });
1336
-
1337
- /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (JClicPlayer);
1338
-
1339
-
1340
- /***/ }),
1341
-
1342
- /***/ 4483:
1343
- /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
1344
-
1345
- /* harmony export */ __webpack_require__.d(__webpack_exports__, {
1346
- /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
1347
- /* harmony export */ });
1348
- /* unused harmony export PlayerHistory */
1349
- /* harmony import */ var jquery__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(7750);
1350
- /* harmony import */ var jquery__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(jquery__WEBPACK_IMPORTED_MODULE_0__);
1351
- /* harmony import */ var _Utils_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(1253);
1352
- /**
1353
- * File : PlayerHistory.js
1354
- * Created : 28/04/2015
1355
- * By : Francesc Busquets <francesc@gmail.com>
1356
- *
1357
- * JClic.js
1358
- * An HTML5 player of JClic activities
1359
- * https://projectestac.github.io/jclic.js
1360
- *
1361
- * @source https://github.com/projectestac/jclic.js
1362
- *
1363
- * @license EUPL-1.2
1364
- * @licstart
1365
- * (c) 2000-2020 Educational Telematic Network of Catalonia (XTEC)
1366
- *
1367
- * Licensed under the EUPL, Version 1.1 or -as soon they will be approved by
1368
- * the European Commission- subsequent versions of the EUPL (the "Licence");
1369
- * You may not use this work except in compliance with the Licence.
1370
- *
1371
- * You may obtain a copy of the Licence at:
1372
- * https://joinup.ec.europa.eu/software/page/eupl
1373
- *
1374
- * Unless required by applicable law or agreed to in writing, software
1375
- * distributed under the Licence is distributed on an "AS IS" basis, WITHOUT
1376
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
1377
- * Licence for the specific language governing permissions and limitations
1378
- * under the Licence.
1379
- * @licend
1380
- * @module
1381
- */
1382
-
1383
- /* global window */
1384
-
1385
-
1386
-
1387
-
1388
- /**
1389
- *
1390
- * PlayerHistory uses an array to store the list of projects and activities done by the user.
1391
- * This class allows {@link module:JClicPlayer.JClicPlayer JClicPlayer} objects to rewind a sequence or to go back to a caller menu.
1392
- */
1393
- class PlayerHistory {
1394
- /**
1395
- * PlayerHistory constructor
1396
- * @param {module:JClicPlayer.JClicPlayer} player - The JClicPlayer associated to this history
1397
- */
1398
- constructor(player) {
1399
- this.player = player;
1400
- this.sequenceStack = [];
1401
- if (window && window.history && player.options.browserHistory) {
1402
- this.browserHistory = true;
1403
- jquery__WEBPACK_IMPORTED_MODULE_0___default()(window).on('popstate', (ev) => {
1404
- const state = ev.originalEvent.state;
1405
- if (state)
1406
- this.processPopStateEvent(state);
1407
- });
1408
- }
1409
- }
1410
-
1411
- /**
1412
- *
1413
- * Process the `state` object received in a `popstate` event
1414
- * @param {PlayerHistory#HistoryElement} state - The previously stored state
1415
- */
1416
- processPopStateEvent(state) {
1417
- (0,_Utils_js__WEBPACK_IMPORTED_MODULE_1__/* .log */ .Rm)('info', 'Processing History popstate event with state:', state);
1418
- this.processingPop = true;
1419
- if (state.projectPath === this.player.project.path &&
1420
- (0,_Utils_js__WEBPACK_IMPORTED_MODULE_1__/* .isEquivalent */ .l2)(state.fullZipPath, this.player.zip ? this.player.zip.fullZipPath : null))
1421
- this.player.load(null, state.activity, null);
1422
- else
1423
- this.player.load(state.fullZipPath || state.projectPath, state.activity, null);
1424
- }
1425
-
1426
- /**
1427
- * Push a new entry on the window.History stack,
1428
- * only when `browserHistory` is true and there is no `popstate` event in progress
1429
- */
1430
- pushBrowserHistory() {
1431
- if (this.browserHistory) {
1432
-
1433
- if (this.processingPop) {
1434
- // A 'popstate' event is currently being processed, so just clear this flag and return
1435
- this.processingPop = false;
1436
- return;
1437
- }
1438
-
1439
- const
1440
- ase = this.player.project.activitySequence,
1441
- act = ase.currentAct,
1442
- title = this.player.actPanel.act.name || 'No name',
1443
- state = new this.HistoryElement(
1444
- this.player.project.path,
1445
- ase.getSequenceForElement(act),
1446
- act,
1447
- this.player.zip ? this.player.zip.fullZipPath : null);
1448
-
1449
- // Push a new history entry, or update the current one if it has no `state`
1450
- if (!window.history.state)
1451
- window.history.replaceState(state, title);
1452
- else
1453
- window.history.pushState(state, title);
1454
- }
1455
- }
1456
-
1457
- /**
1458
- *
1459
- * Counts the number of {@link module:PlayerHistory.PlayerHistory#HistoryElement HistoryElement} objects stored in
1460
- * {@link module:PlayerHistory.PlayerHistory#sequenceStack sequenceStack}
1461
- * @returns {number}
1462
- */
1463
- storedElementsCount() {
1464
- return this.sequenceStack.length;
1465
- }
1466
-
1467
- /**
1468
- *
1469
- * Removes all elements from {@link module:PlayerHistory.PlayerHistory#sequenceStack sequenceStack}
1470
- */
1471
- clearHistory() {
1472
- this.sequenceStack = [0];
1473
- }
1474
-
1475
- /**
1476
- * Adds the current project and activity to the top of the history stack.
1477
- */
1478
- push() {
1479
- if (this.player.project !== null && this.player.project.path !== null) {
1480
- const
1481
- ase = this.player.project.activitySequence,
1482
- act = ase.currentAct;
1483
- if (act >= 0) {
1484
- if (this.sequenceStack.length > 0) {
1485
- const last = this.sequenceStack[this.sequenceStack.length - 1];
1486
- if (last.projectPath === this.player.project.path && last.activity === act)
1487
- return;
1488
- }
1489
- this.sequenceStack.push(
1490
- new this.HistoryElement(
1491
- this.player.project.path,
1492
- ase.getSequenceForElement(act),
1493
- act,
1494
- this.player.zip ? this.player.zip.fullZipPath : null));
1495
- }
1496
- }
1497
- }
1498
-
1499
- /**
1500
- * Retrieves the {@link module:PlayerHistory.PlayerHistory#HistoryElement HistoryElement} placed at the top of the
1501
- * stack (if any) and instructs {@link module:JClicPlayer.JClicPlayer JClicPlayer} to load it. The obtained effect is to
1502
- * "rewind" or "go back", usually to an activity that acts as a menu.
1503
- * @returns {boolean}
1504
- */
1505
- pop() {
1506
- // todo: check return value
1507
- if (this.sequenceStack.length > 0) {
1508
- const e = this.sequenceStack.pop();
1509
- if (e.projectPath === this.player.project.path &&
1510
- (0,_Utils_js__WEBPACK_IMPORTED_MODULE_1__/* .isEquivalent */ .l2)(e.fullZipPath, this.player.zip ? this.player.zip.fullZipPath : null))
1511
- this.player.load(null, e.activity, null);
1512
- else
1513
- if (this.testMode && e.projectPath !== null && e.projectPath.length > 0)
1514
- (0,_Utils_js__WEBPACK_IMPORTED_MODULE_1__/* .log */ .Rm)('info', `At this point, a jump to "${e.projectPath}" should be performed.`);
1515
- else
1516
- this.player.load(e.fullZipPath || e.projectPath, e.activity, null);
1517
- }
1518
- return true;
1519
- }
1520
-
1521
- /**
1522
- *
1523
- * Processes the provided {@link module:bags/JumpInfo.JumpInfo JumpInfo} object, instructing {@link module:JClicPlayer.JClicPlayer JClicPlayer} to go back,
1524
- * stop or jump to another point in the sequence.
1525
- * @param {module:bags/JumpInfo.JumpInfo} ji - The object to be processed
1526
- * @param {boolean} allowReturn - When this parameter is `true`, the jump instructed by `ji` (if any)
1527
- * will be recorded, thus allowing to return to the current activity.
1528
- * @returns {boolean} - `true` if the jump can be processed without errors, `false` otherwise.
1529
- */
1530
- processJump(ji, allowReturn) {
1531
- let result = false;
1532
- if (ji !== null && this.player.project !== null) {
1533
- switch (ji.action) {
1534
- case 'STOP':
1535
- break;
1536
- case 'RETURN':
1537
- if (this.sequenceStack.length > 0 || !this.player.options.returnAsExit) {
1538
- result = this.pop();
1539
- break;
1540
- }
1541
- case 'EXIT':
1542
- if (this.testMode)
1543
- (0,_Utils_js__WEBPACK_IMPORTED_MODULE_1__/* .log */ .Rm)('info', 'At this point, the program should exit.');
1544
- else
1545
- this.player.exit(ji.sequence);
1546
- break;
1547
- case 'JUMP':
1548
- if (!ji.sequence && !ji.projectPath) {
1549
- const ase = this.player.project.activitySequence.getElement(ji.actNum, true);
1550
- if (ase !== null) {
1551
- if (allowReturn)
1552
- this.push();
1553
- this.player.load(null, null, ase.activity);
1554
- result = true;
1555
- }
1556
- } else {
1557
- if (this.testMode && ji.projectPath !== null && ji.projectPath.length > 0) {
1558
- (0,_Utils_js__WEBPACK_IMPORTED_MODULE_1__/* .log */ .Rm)('info', `At this point, a jump to "${ji.projectPath}" should be performed.`);
1559
- } else {
1560
- result = this.jumpToSequence(ji.sequence,
1561
- ji.projectPath ? (0,_Utils_js__WEBPACK_IMPORTED_MODULE_1__/* .getPath */ .Yn)(this.player.project.basePath, ji.projectPath) : null,
1562
- allowReturn);
1563
- }
1564
- }
1565
- break;
1566
- }
1567
- }
1568
- return result;
1569
- }
1570
-
1571
- /**
1572
- * Performs a jump to the specified sequence
1573
- * @param {string} sequence - The {@link module:bags/ActivitySequence.ActivitySequence ActivitySequence} tag to jump to.
1574
- * @param {string} [path] - When not `null`, indicates a new project file that must be loaded.
1575
- * Otherwise, the `sequence` parameter refers to a tag on the {@link module:bags/ActivitySequence.ActivitySequence ActivitySequence} of the
1576
- * current project.
1577
- * @param {boolean} [allowReturn] - When this parameter is `true`, the jump will be recorded, thus
1578
- * allowing to return to the current activity.
1579
- */
1580
- jumpToSequence(sequence, path = null, allowReturn = false) {
1581
- if ((0,_Utils_js__WEBPACK_IMPORTED_MODULE_1__/* .isNullOrUndef */ .Pj)(sequence) && (0,_Utils_js__WEBPACK_IMPORTED_MODULE_1__/* .isNullOrUndef */ .Pj)(path))
1582
- return false;
1583
- if ((0,_Utils_js__WEBPACK_IMPORTED_MODULE_1__/* .isNullOrUndef */ .Pj)(path))
1584
- path = this.player.project.path;
1585
- if (this.sequenceStack.length > 0) {
1586
- const e = this.sequenceStack[this.sequenceStack.length - 1];
1587
- if (!(0,_Utils_js__WEBPACK_IMPORTED_MODULE_1__/* .isNullOrUndef */ .Pj)(sequence) && path === e.projectPath) {
1588
- let same = sequence === e.sequence;
1589
- if (path === this.player.project.path) {
1590
- const ase = this.player.project.activitySequence.getElement(e.activity, false);
1591
- same = ase !== null && sequence === ase.tag;
1592
- }
1593
- if (same)
1594
- return this.pop();
1595
- }
1596
- }
1597
- if (allowReturn)
1598
- this.push();
1599
- if (path === this.player.project.path)
1600
- this.player.load(null, sequence, null);
1601
- else
1602
- this.player.load(path, sequence, null);
1603
- return true;
1604
- }
1605
- }
1606
-
1607
- Object.assign(PlayerHistory.prototype, {
1608
- /**
1609
- * The {@link module:JClicPlayer.JClicPlayer JClicPlayer} object to which this `PlayerHistory` belongs
1610
- * @name module:PlayerHistory.PlayerHistory#player
1611
- * @type {module:JClicPlayer.JClicPlayer} */
1612
- player: null,
1613
- /**
1614
- * This is the main member of the class. PlayerHistory puts and retrieves
1615
- * on it information about the proects and activities done by the current user.
1616
- * @name module:PlayerHistory.PlayerHistory#sequenceStack
1617
- * @type {module:PlayerHistory.PlayerHistory#HistoryElement[]} */
1618
- sequenceStack: [],
1619
- /**
1620
- * When in test mode, jumps are only simulated.
1621
- * @name module:PlayerHistory.PlayerHistory#testMode
1622
- * @type {boolean} */
1623
- testMode: false,
1624
- /**
1625
- * When true, JClic history is in sync with browser history
1626
- * @name PlayerHistory#browserHistory
1627
- * @type {boolean} */
1628
- browserHistory: false,
1629
- /**
1630
- * When true, a window.history event is currently being processed, so window.pushState should not be performed
1631
- * @name PlayerHistory#processingPop
1632
- * @type {boolean} */
1633
- processingPop: false,
1634
- /**
1635
- * Inner class used to store history elements.
1636
- * @name module:PlayerHistory.PlayerHistory#HistoryElement
1637
- */
1638
- HistoryElement: class {
1639
- /**
1640
- * HistoryElement constructor
1641
- * @param {string} projectPath - The full path of the project file
1642
- * @param {string} sequence - The nearest sequence tag
1643
- * @param {number} activity - The index of the current activity on the project's {@link module:bags/ActivitySequence.ActivitySequence ActivitySequence}
1644
- * @param {string} fullZipPath - If `projectPath` resides in a {@link external:JSZip JSZip} object,
1645
- * the full path of the zip file.
1646
- */
1647
- constructor(projectPath, sequence, activity, fullZipPath) {
1648
- this.projectPath = projectPath;
1649
- this.sequence = sequence;
1650
- this.activity = activity;
1651
- this.fullZipPath = fullZipPath;
1652
- }
1653
- }
1654
- });
1655
-
1656
- /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (PlayerHistory);
1657
-
1658
-
1659
- /***/ }),
1660
-
1661
- /***/ 827:
1662
- /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
1663
-
1664
- /* harmony export */ __webpack_require__.d(__webpack_exports__, {
1665
- /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
1666
- /* harmony export */ });
1667
- /* unused harmony export ActiveMediaBag */
1668
- /* harmony import */ var _ActiveMediaPlayer_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(520);
1669
- /* harmony import */ var _Utils_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(1253);
1670
- /**
1671
- * File : media/ActiveMediaBag.js
1672
- * Created : 28/04/2015
1673
- * By : Francesc Busquets <francesc@gmail.com>
1674
- *
1675
- * JClic.js
1676
- * An HTML5 player of JClic activities
1677
- * https://projectestac.github.io/jclic.js
1678
- *
1679
- * @source https://github.com/projectestac/jclic.js
1680
- *
1681
- * @license EUPL-1.2
1682
- * @licstart
1683
- * (c) 2000-2020 Educational Telematic Network of Catalonia (XTEC)
1684
- *
1685
- * Licensed under the EUPL, Version 1.1 or -as soon they will be approved by
1686
- * the European Commission- subsequent versions of the EUPL (the "Licence");
1687
- * You may not use this work except in compliance with the Licence.
1688
- *
1689
- * You may obtain a copy of the Licence at:
1690
- * https://joinup.ec.europa.eu/software/page/eupl
1691
- *
1692
- * Unless required by applicable law or agreed to in writing, software
1693
- * distributed under the Licence is distributed on an "AS IS" basis, WITHOUT
1694
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
1695
- * Licence for the specific language governing permissions and limitations
1696
- * under the Licence.
1697
- * @licend
1698
- * @module
1699
- */
1700
-
1701
-
1702
-
1703
-
1704
- /**
1705
- * This class stores a collection of realized {@link module:media/ActiveMediaPlayer.ActiveMediaPlayer ActiveMediaPlayer} objects, related to a
1706
- * {@link module:project/JClicProject.JClicProject JClicProject} or {@link module:Activity.Activity Activity}.
1707
- */
1708
- class ActiveMediaBag {
1709
- /**
1710
- * ActiveMediaBag constructor
1711
- */
1712
- constructor() {
1713
- this.players = [];
1714
- }
1715
-
1716
- /**
1717
- * Creates a new {@link module:media/ActiveMediaPlayer.ActiveMediaPlayer ActiveMediaPlayer} linked to this media bag
1718
- * @param {module:media/MediaContent.MediaContent} mc - The content used by the new player
1719
- * @param {module:bags/MediaBag.MediaBag} mb - The project's MediaBag
1720
- * @param {module:JClicPlayer.JClicPlayer} ps - An object implementing the
1721
- * [PlayStation](http://projectestac.github.io/jclic/apidoc/edu/xtec/jclic/PlayStation.html) interface,
1722
- * usually a {@link module:JClicPlayer.JClicPlayer JClicPlayer}.
1723
- * @returns {module:media/ActiveMediaPlayer.ActiveMediaPlayer}
1724
- */
1725
- createActiveMediaPlayer(mc, mb, ps) {
1726
- let amp = null;
1727
- switch (mc.type) {
1728
- case 'RECORD_AUDIO':
1729
- if (mc.length <= 0 || mc.length >= _Utils_js__WEBPACK_IMPORTED_MODULE_1__/* .settings */ .W0.MAX_RECORD_LENGTH)
1730
- break;
1731
- /* falls through */
1732
- case 'PLAY_RECORDED_AUDIO':
1733
- if (mc.recBuffer < 0 || mc.recBuffer >= 10)
1734
- break;
1735
- /* falls through */
1736
- case 'PLAY_AUDIO':
1737
- case 'PLAY_MIDI':
1738
- case 'PLAY_VIDEO':
1739
- amp = new _ActiveMediaPlayer_js__WEBPACK_IMPORTED_MODULE_0__["default"](mc, mb, ps);
1740
- break;
1741
- }
1742
- if (amp !== null)
1743
- this.players.push(amp);
1744
- return amp;
1745
- }
1746
-
1747
- /**
1748
- * Looks for an already existing {@link module:media/ActiveMediaPlayer.ActiveMediaPlayer ActiveMediaPlayer} equivalent to the requested.
1749
- * When not found, a new one is created and and returned.
1750
- * @param {module:media/MediaContent.MediaContent} mc - The content used by the new player
1751
- * @param {module:bags/MediaBag.MediaBag} mb - The project's MediaBag
1752
- * @param {module:JClicPlayer.JClicPlayer} ps - An object implementing the
1753
- * {@link http://projectestac.github.io/jclic/apidoc/edu/xtec/jclic/PlayStation.html|PlayStation} interface,
1754
- * usually a {@link module:JClicPlayer.JClicPlayer JClicPlayer}.
1755
- * @returns {module:media/ActiveMediaPlayer.ActiveMediaPlayer}
1756
- */
1757
- getActiveMediaPlayer(mc, mb, ps) {
1758
- return this.players.find(p => p.mc === mc || p.mc.isEquivalent(mc))
1759
- || this.createActiveMediaPlayer(mc, mb, ps);
1760
- }
1761
-
1762
- /**
1763
- * Removes from the list of players the {@link module:media/ActiveMediaPlayer.ActiveMediaPlayer ActiveMediaPlayer} related to the specified {@link module:media/MediaContent.MediaContent}.
1764
- * @param {module:media/MediaContent.MediaContent} mc - The media content to look for.
1765
- */
1766
- removeActiveMediaPlayer(mc) {
1767
- const i = this.players.findIndex(p => p.mc === mc);
1768
- if (i >= 0) {
1769
- this.players[i].clear();
1770
- // removes the element pointed by 'i'
1771
- this.players.splice(i, 1);
1772
- }
1773
- }
1774
-
1775
- /**
1776
- * Realizes all the media elements stored in this bag
1777
- */
1778
- realizeAll() {
1779
- this.players.forEach(p => p.realize());
1780
- }
1781
-
1782
- /**
1783
- * Stops playing all media elements stored in this bag
1784
- * @param {number} level - Level at and below what all media players will be muted.
1785
- */
1786
- stopAll(level) {
1787
- if (typeof level === 'undefined')
1788
- level = -1;
1789
- this.players.forEach(amp => {
1790
- if (level === -1 || amp.mc !== null && amp.mc.level <= level)
1791
- amp.stop();
1792
- });
1793
- }
1794
-
1795
- /**
1796
- * Removes all players from this media bag
1797
- */
1798
- removeAll() {
1799
- this.players.forEach(p => p.clear());
1800
- // Empty the `players` array
1801
- this.players.length = 0;
1802
- _ActiveMediaPlayer_js__WEBPACK_IMPORTED_MODULE_0__["default"].prototype.clearAllAudioBuffers();
1803
- }
1804
- }
1805
-
1806
- Object.assign(ActiveMediaBag.prototype, {
1807
- /**
1808
- * The collection of {@link module:media/ActiveMediaPlayer.ActiveMediaPlayer ActiveMediaPlayer} objects stored in this media bag.
1809
- * @name module:media/ActiveMediaBag.ActiveMediaBag#players
1810
- * @type {module:media/ActiveMediaPlayer.ActiveMediaPlayer[]} */
1811
- players: [],
1812
- });
1813
-
1814
- /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (ActiveMediaBag);
1815
-
1816
-
1817
- /***/ })
1818
-
1819
- };
1820
- ;
1821
- //# sourceMappingURL=696.jclic-node.js.map