@oat-sa/tao-core-ui 1.5.4 → 1.6.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ckeditor/ckConfigurator.js +9 -1
- package/dist/mediaEditor/mediaEditorComponent.js +5 -3
- package/dist/mediaEditor/plugins/mediaDimension/mediaDimensionComponent.js +46 -25
- package/dist/mediaplayer/css/player.css +104 -14
- package/dist/mediaplayer/css/player.css.map +1 -1
- package/dist/mediaplayer/players/html5.js +767 -0
- package/dist/mediaplayer/players/youtube.js +470 -0
- package/dist/mediaplayer/players.js +35 -0
- package/dist/mediaplayer/support.js +134 -0
- package/dist/mediaplayer/utils/reminder.js +198 -0
- package/dist/mediaplayer/utils/timeObserver.js +149 -0
- package/dist/mediaplayer/youtubeManager.js +177 -0
- package/dist/mediaplayer.js +1251 -1912
- package/dist/previewer.js +25 -19
- package/package.json +1 -1
- package/scss/basic.scss +1 -0
- package/scss/inc/_jquery.nouislider.scss +254 -0
- package/src/ckeditor/ckConfigurator.js +10 -1
- package/src/itemButtonList/css/item-button-list.css +225 -0
- package/src/itemButtonList/css/item-button-list.css.map +1 -0
- package/src/mediaEditor/mediaEditorComponent.js +25 -26
- package/src/mediaEditor/plugins/mediaDimension/mediaDimensionComponent.js +83 -63
- package/src/mediaplayer/css/player.css +104 -14
- package/src/mediaplayer/css/player.css.map +1 -1
- package/src/mediaplayer/players/html5.js +564 -0
- package/src/mediaplayer/players/youtube.js +323 -0
- package/src/mediaplayer/players.js +29 -0
- package/src/mediaplayer/scss/player.scss +125 -16
- package/src/mediaplayer/support.js +126 -0
- package/src/mediaplayer/tpl/audio.tpl +6 -0
- package/src/mediaplayer/tpl/player.tpl +11 -32
- package/src/mediaplayer/tpl/source.tpl +1 -0
- package/src/mediaplayer/tpl/video.tpl +6 -0
- package/src/mediaplayer/tpl/youtube.tpl +1 -0
- package/src/mediaplayer/utils/reminder.js +184 -0
- package/src/mediaplayer/utils/timeObserver.js +143 -0
- package/src/mediaplayer/youtubeManager.js +161 -0
- package/src/mediaplayer.js +1217 -1901
- package/src/previewer.js +40 -33
- package/src/searchModal/css/advancedSearch.css +190 -0
- package/src/searchModal/css/advancedSearch.css.map +1 -0
- package/src/searchModal/css/searchModal.css +506 -0
- package/src/searchModal/css/searchModal.css.map +1 -0
|
@@ -0,0 +1,470 @@
|
|
|
1
|
+
define(['jquery', 'core/eventifier', 'ui/mediaplayer/support', 'ui/mediaplayer/youtubeManager', 'handlebars', 'i18n', 'lodash', 'lib/dompurify/purify'], function ($$1, eventifier, support, youtubeManagerFactory, Handlebars, __, _, DOMPurify) { 'use strict';
|
|
2
|
+
|
|
3
|
+
$$1 = $$1 && $$1.hasOwnProperty('default') ? $$1['default'] : $$1;
|
|
4
|
+
eventifier = eventifier && eventifier.hasOwnProperty('default') ? eventifier['default'] : eventifier;
|
|
5
|
+
support = support && support.hasOwnProperty('default') ? support['default'] : support;
|
|
6
|
+
youtubeManagerFactory = youtubeManagerFactory && youtubeManagerFactory.hasOwnProperty('default') ? youtubeManagerFactory['default'] : youtubeManagerFactory;
|
|
7
|
+
Handlebars = Handlebars && Handlebars.hasOwnProperty('default') ? Handlebars['default'] : Handlebars;
|
|
8
|
+
__ = __ && __.hasOwnProperty('default') ? __['default'] : __;
|
|
9
|
+
_ = _ && _.hasOwnProperty('default') ? _['default'] : _;
|
|
10
|
+
DOMPurify = DOMPurify && DOMPurify.hasOwnProperty('default') ? DOMPurify['default'] : DOMPurify;
|
|
11
|
+
|
|
12
|
+
function _typeof(obj) {
|
|
13
|
+
"@babel/helpers - typeof";
|
|
14
|
+
|
|
15
|
+
if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
|
|
16
|
+
_typeof = function (obj) {
|
|
17
|
+
return typeof obj;
|
|
18
|
+
};
|
|
19
|
+
} else {
|
|
20
|
+
_typeof = function (obj) {
|
|
21
|
+
return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return _typeof(obj);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function Helpers0 (hb) {
|
|
29
|
+
//register a i18n helper
|
|
30
|
+
hb.registerHelper('__', function (key) {
|
|
31
|
+
return __(key);
|
|
32
|
+
});
|
|
33
|
+
/**
|
|
34
|
+
* Register dompurify helper
|
|
35
|
+
*
|
|
36
|
+
* https://github.com/cure53/DOMPurify
|
|
37
|
+
* with config SAFE_FOR_TEMPLATES: true
|
|
38
|
+
* to make output safe for template systems
|
|
39
|
+
*/
|
|
40
|
+
|
|
41
|
+
hb.registerHelper('dompurify', function (context) {
|
|
42
|
+
return DOMPurify.sanitize(context);
|
|
43
|
+
});
|
|
44
|
+
/**
|
|
45
|
+
* Register join helper
|
|
46
|
+
*
|
|
47
|
+
* Example :
|
|
48
|
+
* var values = {a:v1, b:v2, c:v3};
|
|
49
|
+
* Using {{{join attributes '=' ' ' '"'}}} will return : a="v1" b="v2" c="v3"
|
|
50
|
+
* Using {{{join values null ' or ' '*'}}} will return : *v1* or *v2* or *v3*
|
|
51
|
+
*/
|
|
52
|
+
|
|
53
|
+
hb.registerHelper('join', function (arr, keyValueGlue, fragmentGlue, wrapper) {
|
|
54
|
+
var fragments = [];
|
|
55
|
+
keyValueGlue = typeof keyValueGlue === 'string' ? keyValueGlue : undefined;
|
|
56
|
+
fragmentGlue = typeof fragmentGlue === 'string' ? fragmentGlue : ' ';
|
|
57
|
+
wrapper = typeof wrapper === 'string' ? wrapper : '"';
|
|
58
|
+
|
|
59
|
+
_.forIn(arr, function (value, key) {
|
|
60
|
+
var fragment = '';
|
|
61
|
+
|
|
62
|
+
if (value !== null || value !== undefined) {
|
|
63
|
+
if (typeof value === 'boolean') {
|
|
64
|
+
value = value ? 'true' : 'false';
|
|
65
|
+
} else if (_typeof(value) === 'object') {
|
|
66
|
+
value = _.values(value).join(' ');
|
|
67
|
+
}
|
|
68
|
+
} else {
|
|
69
|
+
value = '';
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (keyValueGlue !== undefined) {
|
|
73
|
+
fragment += key + keyValueGlue;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
fragment += wrapper + value + wrapper;
|
|
77
|
+
fragments.push(fragment);
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
return fragments.join(fragmentGlue);
|
|
81
|
+
}); //register a classic "for loop" helper
|
|
82
|
+
//it also adds a local variable "i" as the index in each iteration loop
|
|
83
|
+
|
|
84
|
+
hb.registerHelper('for', function (startIndex, stopIndex, increment, options) {
|
|
85
|
+
var ret = '';
|
|
86
|
+
startIndex = parseInt(startIndex);
|
|
87
|
+
stopIndex = parseInt(stopIndex);
|
|
88
|
+
increment = parseInt(increment);
|
|
89
|
+
|
|
90
|
+
for (var i = startIndex; i < stopIndex; i += increment) {
|
|
91
|
+
ret += options.fn(_.extend({}, this, {
|
|
92
|
+
i: i
|
|
93
|
+
}));
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return ret;
|
|
97
|
+
});
|
|
98
|
+
hb.registerHelper('equal', function (var1, var2, options) {
|
|
99
|
+
if (var1 == var2) {
|
|
100
|
+
return options.fn(this);
|
|
101
|
+
} else {
|
|
102
|
+
return options.inverse(this);
|
|
103
|
+
}
|
|
104
|
+
}); // register a "get property" helper
|
|
105
|
+
// it gets the named property from the provided context
|
|
106
|
+
|
|
107
|
+
hb.registerHelper('property', function (name, context) {
|
|
108
|
+
return context[name] || '';
|
|
109
|
+
}); // register an 'includes' helper
|
|
110
|
+
// it checks if value is in array
|
|
111
|
+
|
|
112
|
+
hb.registerHelper('includes', function (haystack, needle, options) {
|
|
113
|
+
if (_.contains(haystack, needle)) {
|
|
114
|
+
return options.fn(this);
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
if (!Helpers0.__initialized) {
|
|
120
|
+
Helpers0(Handlebars);
|
|
121
|
+
Helpers0.__initialized = true;
|
|
122
|
+
}
|
|
123
|
+
var Template = Handlebars.template(function (Handlebars,depth0,helpers,partials,data) {
|
|
124
|
+
this.compilerInfo = [4,'>= 1.0.0'];
|
|
125
|
+
helpers = this.merge(helpers, Handlebars.helpers); data = data || {};
|
|
126
|
+
var buffer = "", stack1, helper, functionType="function", escapeExpression=this.escapeExpression;
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
buffer += "<div class=\"media video youtube\" data-video-src=\"";
|
|
130
|
+
if (helper = helpers.src) { stack1 = helper.call(depth0, {hash:{},data:data}); }
|
|
131
|
+
else { helper = (depth0 && depth0.src); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
|
|
132
|
+
buffer += escapeExpression(stack1)
|
|
133
|
+
+ "\" data-video-id=\"";
|
|
134
|
+
if (helper = helpers.id) { stack1 = helper.call(depth0, {hash:{},data:data}); }
|
|
135
|
+
else { helper = (depth0 && depth0.id); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
|
|
136
|
+
buffer += escapeExpression(stack1)
|
|
137
|
+
+ "\" data-type=\"youtube\"></div>\n";
|
|
138
|
+
return buffer;
|
|
139
|
+
});
|
|
140
|
+
function youtubeTpl(data, options, asString) {
|
|
141
|
+
var html = Template(data, options);
|
|
142
|
+
return (asString || true) ? html : $(html);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* This program is free software; you can redistribute it and/or
|
|
147
|
+
* modify it under the terms of the GNU General Public License
|
|
148
|
+
* as published by the Free Software Foundation; under version 2
|
|
149
|
+
* of the License (non-upgradable).
|
|
150
|
+
*
|
|
151
|
+
* This program is distributed in the hope that it will be useful,
|
|
152
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
153
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
154
|
+
* GNU General Public License for more details.
|
|
155
|
+
*
|
|
156
|
+
* You should have received a copy of the GNU General Public License
|
|
157
|
+
* along with this program; if not, write to the Free Software
|
|
158
|
+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
159
|
+
*
|
|
160
|
+
* Copyright (c) 2015-2021 (original work) Open Assessment Technologies SA ;
|
|
161
|
+
*/
|
|
162
|
+
/**
|
|
163
|
+
* The polling interval used to update the progress bar while playing a YouTube video.
|
|
164
|
+
* Note : the YouTube API does not provide events to update this progress bar...
|
|
165
|
+
* @type {Number}
|
|
166
|
+
*/
|
|
167
|
+
|
|
168
|
+
var youtubePolling = 100;
|
|
169
|
+
/**
|
|
170
|
+
* List of YouTube events that can be listened to for debugging
|
|
171
|
+
* @type {String[]}
|
|
172
|
+
*/
|
|
173
|
+
|
|
174
|
+
var youtubeEvents = ['onApiChange', 'onError', 'onPlaybackQualityChange', 'onPlaybackRateChange', 'onStateChange'];
|
|
175
|
+
/**
|
|
176
|
+
* List of player events that can be listened to for debugging
|
|
177
|
+
* @type {String[]}
|
|
178
|
+
*/
|
|
179
|
+
|
|
180
|
+
var playerEvents = ['end', 'error', 'pause', 'play', 'ready', 'resize', 'timeupdate'];
|
|
181
|
+
/**
|
|
182
|
+
* A local manager for Youtube players.
|
|
183
|
+
* Relies on https://developers.google.com/youtube/iframe_api_reference
|
|
184
|
+
* @type {Object}
|
|
185
|
+
*/
|
|
186
|
+
|
|
187
|
+
var youtubeManager = youtubeManagerFactory();
|
|
188
|
+
/**
|
|
189
|
+
* Defines a player object dedicated to youtube media
|
|
190
|
+
* @param {jQuery} $container - Where to render the player
|
|
191
|
+
* @param {Object} config - The list of config entries
|
|
192
|
+
* @param {Array} config.sources - The list of media sources
|
|
193
|
+
* @param {Boolean} [config.debug] - Enables the debug mode
|
|
194
|
+
* @param {Number} [config.polling=100] - The polling interval used to update the progress bar while playing a YouTube video.
|
|
195
|
+
* @returns {Object} player
|
|
196
|
+
*/
|
|
197
|
+
|
|
198
|
+
function youtubePlayerFactory($container) {
|
|
199
|
+
var config = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
200
|
+
var sources = config.sources || [];
|
|
201
|
+
var source = sources[0] || {};
|
|
202
|
+
var otherSources = sources.slice(1);
|
|
203
|
+
config.polling = config.polling || youtubePolling;
|
|
204
|
+
var $media;
|
|
205
|
+
var media;
|
|
206
|
+
var interval;
|
|
207
|
+
var destroyed;
|
|
208
|
+
var initWidth;
|
|
209
|
+
var initHeight;
|
|
210
|
+
var callbacks = []; // eslint-disable-next-line
|
|
211
|
+
|
|
212
|
+
var debug = function debug(action) {
|
|
213
|
+
var _window$console;
|
|
214
|
+
|
|
215
|
+
for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
|
|
216
|
+
args[_key - 1] = arguments[_key];
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
return config.debug && (_window$console = window.console).log.apply(_window$console, ["[youtube:".concat(action, "]")].concat(args));
|
|
220
|
+
};
|
|
221
|
+
|
|
222
|
+
var queueMedia = function queueMedia(url, register) {
|
|
223
|
+
var id = youtubeManager.extractYoutubeId(url);
|
|
224
|
+
|
|
225
|
+
if (id) {
|
|
226
|
+
if (media) {
|
|
227
|
+
register(id);
|
|
228
|
+
} else {
|
|
229
|
+
callbacks.push(function () {
|
|
230
|
+
return register(id);
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
return true;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
return false;
|
|
238
|
+
};
|
|
239
|
+
|
|
240
|
+
var player = {
|
|
241
|
+
init: function init() {
|
|
242
|
+
var _this = this;
|
|
243
|
+
|
|
244
|
+
$media = $$1(youtubeTpl({
|
|
245
|
+
src: source.src,
|
|
246
|
+
id: youtubeManager.extractYoutubeId(source.src)
|
|
247
|
+
}));
|
|
248
|
+
$container.append($media);
|
|
249
|
+
otherSources.forEach(function (source) {
|
|
250
|
+
return _this.addMedia(source.src);
|
|
251
|
+
});
|
|
252
|
+
media = null;
|
|
253
|
+
destroyed = false;
|
|
254
|
+
youtubeManager.add($media, this, {
|
|
255
|
+
controls: !support.canControl()
|
|
256
|
+
});
|
|
257
|
+
return true;
|
|
258
|
+
},
|
|
259
|
+
onReady: function onReady(event) {
|
|
260
|
+
var _this2 = this;
|
|
261
|
+
|
|
262
|
+
media = event.target;
|
|
263
|
+
$media = $$1(media.getIframe()); // the injected media placeholder is replaced by an iframe by the YouTube lib
|
|
264
|
+
|
|
265
|
+
if (!destroyed) {
|
|
266
|
+
// install debug logger
|
|
267
|
+
if (config.debug) {
|
|
268
|
+
debug('installed', media);
|
|
269
|
+
youtubeEvents.forEach(function (eventName) {
|
|
270
|
+
return media.addEventListener(eventName, function (e) {
|
|
271
|
+
debug('media event', eventName, $media && $media.data('videoSrc'), e);
|
|
272
|
+
});
|
|
273
|
+
});
|
|
274
|
+
playerEvents.forEach(function (eventName) {
|
|
275
|
+
_this2.on(eventName, function () {
|
|
276
|
+
for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
|
|
277
|
+
args[_key2] = arguments[_key2];
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
debug.apply(void 0, ['player event', eventName, $media && $media.data('videoSrc')].concat(args));
|
|
281
|
+
});
|
|
282
|
+
});
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
if (initWidth && initHeight) {
|
|
286
|
+
this.setSize(initWidth, initHeight);
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
callbacks.forEach(function (cb) {
|
|
290
|
+
return cb();
|
|
291
|
+
});
|
|
292
|
+
callbacks = [];
|
|
293
|
+
this.trigger('ready');
|
|
294
|
+
} else {
|
|
295
|
+
this.destroy();
|
|
296
|
+
}
|
|
297
|
+
},
|
|
298
|
+
onStateChange: function onStateChange(event) {
|
|
299
|
+
this.stopPolling();
|
|
300
|
+
|
|
301
|
+
if (!destroyed) {
|
|
302
|
+
switch (event.data) {
|
|
303
|
+
// ended
|
|
304
|
+
case 0:
|
|
305
|
+
this.trigger('end');
|
|
306
|
+
break;
|
|
307
|
+
// playing
|
|
308
|
+
|
|
309
|
+
case 1:
|
|
310
|
+
this.trigger('play');
|
|
311
|
+
this.startPolling();
|
|
312
|
+
break;
|
|
313
|
+
// paused
|
|
314
|
+
|
|
315
|
+
case 2:
|
|
316
|
+
this.trigger('pause');
|
|
317
|
+
break;
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
},
|
|
321
|
+
stopPolling: function stopPolling() {
|
|
322
|
+
if (interval) {
|
|
323
|
+
window.clearInterval(interval);
|
|
324
|
+
interval = null;
|
|
325
|
+
}
|
|
326
|
+
},
|
|
327
|
+
startPolling: function startPolling() {
|
|
328
|
+
var _this3 = this;
|
|
329
|
+
|
|
330
|
+
interval = window.setInterval(function () {
|
|
331
|
+
return _this3.trigger('timeupdate');
|
|
332
|
+
}, config.polling);
|
|
333
|
+
},
|
|
334
|
+
destroy: function destroy() {
|
|
335
|
+
debug('api call', 'destroy');
|
|
336
|
+
destroyed = true;
|
|
337
|
+
this.stopPolling();
|
|
338
|
+
this.removeAllListeners();
|
|
339
|
+
|
|
340
|
+
if (media) {
|
|
341
|
+
youtubeEvents.forEach(function (ev) {
|
|
342
|
+
return media.removeEventListener(ev);
|
|
343
|
+
});
|
|
344
|
+
media.destroy();
|
|
345
|
+
media = void 0;
|
|
346
|
+
} else {
|
|
347
|
+
youtubeManager.remove($media, this);
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
if ($media) {
|
|
351
|
+
$media.remove();
|
|
352
|
+
$media = void 0;
|
|
353
|
+
}
|
|
354
|
+
},
|
|
355
|
+
getMedia: function getMedia() {
|
|
356
|
+
debug('api call', 'getMedia', media);
|
|
357
|
+
return media;
|
|
358
|
+
},
|
|
359
|
+
getPosition: function getPosition() {
|
|
360
|
+
var position = 0;
|
|
361
|
+
|
|
362
|
+
if (media) {
|
|
363
|
+
position = media.getCurrentTime();
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
debug('api call', 'getPosition', position);
|
|
367
|
+
return position;
|
|
368
|
+
},
|
|
369
|
+
getDuration: function getDuration() {
|
|
370
|
+
var duration = 0;
|
|
371
|
+
|
|
372
|
+
if (media) {
|
|
373
|
+
duration = media.getDuration();
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
debug('api call', 'getDuration', duration);
|
|
377
|
+
return duration;
|
|
378
|
+
},
|
|
379
|
+
getVolume: function getVolume() {
|
|
380
|
+
var volume = 0;
|
|
381
|
+
|
|
382
|
+
if (media) {
|
|
383
|
+
volume = media.getVolume();
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
debug('api call', 'getVolume', volume);
|
|
387
|
+
return volume;
|
|
388
|
+
},
|
|
389
|
+
setVolume: function setVolume(volume) {
|
|
390
|
+
debug('api call', 'setVolume', volume);
|
|
391
|
+
|
|
392
|
+
if (media) {
|
|
393
|
+
media.setVolume(parseFloat(volume));
|
|
394
|
+
}
|
|
395
|
+
},
|
|
396
|
+
setSize: function setSize(width, height) {
|
|
397
|
+
debug('api call', 'setSize', width, height);
|
|
398
|
+
this.trigger('resize', width, height);
|
|
399
|
+
|
|
400
|
+
if (!media) {
|
|
401
|
+
initWidth = width;
|
|
402
|
+
initHeight = height;
|
|
403
|
+
}
|
|
404
|
+
},
|
|
405
|
+
seek: function seek(time) {
|
|
406
|
+
debug('api call', 'seek', time);
|
|
407
|
+
|
|
408
|
+
if (media) {
|
|
409
|
+
media.seekTo(parseFloat(time), true);
|
|
410
|
+
}
|
|
411
|
+
},
|
|
412
|
+
play: function play() {
|
|
413
|
+
debug('api call', 'play');
|
|
414
|
+
|
|
415
|
+
if (media) {
|
|
416
|
+
media.playVideo();
|
|
417
|
+
}
|
|
418
|
+
},
|
|
419
|
+
pause: function pause() {
|
|
420
|
+
debug('api call', 'pause');
|
|
421
|
+
|
|
422
|
+
if (media) {
|
|
423
|
+
media.pauseVideo();
|
|
424
|
+
}
|
|
425
|
+
},
|
|
426
|
+
stop: function stop() {
|
|
427
|
+
debug('api call', 'stop');
|
|
428
|
+
|
|
429
|
+
if (media) {
|
|
430
|
+
media.stopVideo();
|
|
431
|
+
this.trigger('end');
|
|
432
|
+
}
|
|
433
|
+
},
|
|
434
|
+
mute: function mute(state) {
|
|
435
|
+
debug('api call', 'mute', state);
|
|
436
|
+
|
|
437
|
+
if (media) {
|
|
438
|
+
media[state ? 'mute' : 'unMute']();
|
|
439
|
+
}
|
|
440
|
+
},
|
|
441
|
+
isMuted: function isMuted() {
|
|
442
|
+
var mute = false;
|
|
443
|
+
|
|
444
|
+
if (media) {
|
|
445
|
+
mute = media.isMuted();
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
debug('api call', 'isMuted', mute);
|
|
449
|
+
return mute;
|
|
450
|
+
},
|
|
451
|
+
addMedia: function addMedia(url) {
|
|
452
|
+
debug('api call', 'addMedia', url);
|
|
453
|
+
return queueMedia(url, function (id) {
|
|
454
|
+
return media && media.cueVideoById(id);
|
|
455
|
+
});
|
|
456
|
+
},
|
|
457
|
+
setMedia: function setMedia(url) {
|
|
458
|
+
debug('api call', 'setMedia', url);
|
|
459
|
+
callbacks = [];
|
|
460
|
+
return queueMedia(url, function (id) {
|
|
461
|
+
return media && media.loadVideoById(id);
|
|
462
|
+
});
|
|
463
|
+
}
|
|
464
|
+
};
|
|
465
|
+
return eventifier(player);
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
return youtubePlayerFactory;
|
|
469
|
+
|
|
470
|
+
});
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
define(['ui/mediaplayer/players/html5', 'ui/mediaplayer/players/youtube'], function (html5PlayerFactory, youtubePlayerFactory) { 'use strict';
|
|
2
|
+
|
|
3
|
+
html5PlayerFactory = html5PlayerFactory && html5PlayerFactory.hasOwnProperty('default') ? html5PlayerFactory['default'] : html5PlayerFactory;
|
|
4
|
+
youtubePlayerFactory = youtubePlayerFactory && youtubePlayerFactory.hasOwnProperty('default') ? youtubePlayerFactory['default'] : youtubePlayerFactory;
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* This program is free software; you can redistribute it and/or
|
|
8
|
+
* modify it under the terms of the GNU General Public License
|
|
9
|
+
* as published by the Free Software Foundation; under version 2
|
|
10
|
+
* of the License (non-upgradable).
|
|
11
|
+
*
|
|
12
|
+
* This program is distributed in the hope that it will be useful,
|
|
13
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
14
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
15
|
+
* GNU General Public License for more details.
|
|
16
|
+
*
|
|
17
|
+
* You should have received a copy of the GNU General Public License
|
|
18
|
+
* along with this program; if not, write to the Free Software
|
|
19
|
+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
20
|
+
*
|
|
21
|
+
* Copyright (c) 2015-2021 (original work) Open Assessment Technologies SA ;
|
|
22
|
+
*/
|
|
23
|
+
/**
|
|
24
|
+
* Defines the list of available players
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
var players = {
|
|
28
|
+
audio: html5PlayerFactory,
|
|
29
|
+
video: html5PlayerFactory,
|
|
30
|
+
youtube: youtubePlayerFactory
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
return players;
|
|
34
|
+
|
|
35
|
+
});
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
define(function () { 'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* This program is free software; you can redistribute it and/or
|
|
5
|
+
* modify it under the terms of the GNU General Public License
|
|
6
|
+
* as published by the Free Software Foundation; under version 2
|
|
7
|
+
* of the License (non-upgradable).
|
|
8
|
+
*
|
|
9
|
+
* This program is distributed in the hope that it will be useful,
|
|
10
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
11
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
12
|
+
* GNU General Public License for more details.
|
|
13
|
+
*
|
|
14
|
+
* You should have received a copy of the GNU General Public License
|
|
15
|
+
* along with this program; if not, write to the Free Software
|
|
16
|
+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
17
|
+
*
|
|
18
|
+
* Copyright (c) 2015-2021 (original work) Open Assessment Technologies SA ;
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* A Regex to detect Apple mobile browsers
|
|
23
|
+
* @type {RegExp}
|
|
24
|
+
* @private
|
|
25
|
+
*/
|
|
26
|
+
var reAppleMobiles = /ip(hone|od)/i;
|
|
27
|
+
/**
|
|
28
|
+
* A list of MIME types with codec declaration
|
|
29
|
+
* @type {Object}
|
|
30
|
+
* @private
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
var supportedMimeTypes = {
|
|
34
|
+
// video
|
|
35
|
+
'video/webm': 'video/webm; codecs="vp8, vorbis"',
|
|
36
|
+
'video/mp4': 'video/mp4; codecs="avc1.42E01E, mp4a.40.2"',
|
|
37
|
+
'video/ogg': 'video/ogg; codecs="theora, vorbis"',
|
|
38
|
+
// audio
|
|
39
|
+
'audio/mpeg': 'audio/mpeg;',
|
|
40
|
+
'audio/mp4': 'audio/mp4; codecs="mp4a.40.5"',
|
|
41
|
+
'audio/ogg': 'audio/ogg; codecs="vorbis"',
|
|
42
|
+
'audio/wav': 'audio/wav; codecs="1"'
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* Checks support for a MIME type.
|
|
46
|
+
* @param {HTMLMediaElement} media The media element on which check support
|
|
47
|
+
* @param {String} mimeType A MIME type to check the support for
|
|
48
|
+
* @returns {string}
|
|
49
|
+
* @private
|
|
50
|
+
*/
|
|
51
|
+
|
|
52
|
+
var findSupport = function findSupport(media, mimeType) {
|
|
53
|
+
return media.canPlayType(mimeType).replace(/no/, '');
|
|
54
|
+
};
|
|
55
|
+
/**
|
|
56
|
+
* Support detection
|
|
57
|
+
* @type {Object}
|
|
58
|
+
*/
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
var support = {
|
|
62
|
+
/**
|
|
63
|
+
* Checks if the browser can play media
|
|
64
|
+
* @param {HTMLMediaElement} media The media element on which check support
|
|
65
|
+
* @param {String} [mimeType] An optional MIME type to precise the support
|
|
66
|
+
* @returns {Boolean}
|
|
67
|
+
* @private
|
|
68
|
+
*/
|
|
69
|
+
checkSupport: function checkSupport(media, mimeType) {
|
|
70
|
+
var support = media.canPlayType;
|
|
71
|
+
|
|
72
|
+
if (support && mimeType) {
|
|
73
|
+
return !!(supportedMimeTypes[mimeType] && findSupport(media, supportedMimeTypes[mimeType]) || findSupport(media, mimeType));
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return !!support;
|
|
77
|
+
},
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Checks if the browser can play video and audio
|
|
81
|
+
* @param {String} [type] The type of media (audio or video)
|
|
82
|
+
* @param {String} [mime] A media MIME type to check
|
|
83
|
+
* @returns {Boolean}
|
|
84
|
+
*/
|
|
85
|
+
canPlay: function canPlay(type, mime) {
|
|
86
|
+
if (type) {
|
|
87
|
+
switch (type.toLowerCase()) {
|
|
88
|
+
case 'audio':
|
|
89
|
+
return this.canPlayAudio(mime);
|
|
90
|
+
|
|
91
|
+
case 'youtube':
|
|
92
|
+
return this.canPlayVideo();
|
|
93
|
+
|
|
94
|
+
case 'video':
|
|
95
|
+
return this.canPlayVideo(mime);
|
|
96
|
+
|
|
97
|
+
default:
|
|
98
|
+
return false;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
return this.canPlayAudio() && this.canPlayVideo();
|
|
103
|
+
},
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Checks if the browser can play audio
|
|
107
|
+
* @param {String} [mime] A media MIME type to check
|
|
108
|
+
* @returns {Boolean}
|
|
109
|
+
*/
|
|
110
|
+
canPlayAudio: function canPlayAudio(mime) {
|
|
111
|
+
return this.checkSupport(document.createElement('audio'), mime);
|
|
112
|
+
},
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Checks if the browser can play video
|
|
116
|
+
* @param {String} [mime] A media MIME type to check
|
|
117
|
+
* @returns {Boolean}
|
|
118
|
+
*/
|
|
119
|
+
canPlayVideo: function canPlayVideo(mime) {
|
|
120
|
+
return this.checkSupport(document.createElement('video'), mime);
|
|
121
|
+
},
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Checks if the browser allows to control the media playback
|
|
125
|
+
* @returns {Boolean}
|
|
126
|
+
*/
|
|
127
|
+
canControl: function canControl() {
|
|
128
|
+
return !reAppleMobiles.test(window.navigator.userAgent);
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
return support;
|
|
133
|
+
|
|
134
|
+
});
|