@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.
Files changed (43) hide show
  1. package/dist/ckeditor/ckConfigurator.js +9 -1
  2. package/dist/mediaEditor/mediaEditorComponent.js +5 -3
  3. package/dist/mediaEditor/plugins/mediaDimension/mediaDimensionComponent.js +46 -25
  4. package/dist/mediaplayer/css/player.css +104 -14
  5. package/dist/mediaplayer/css/player.css.map +1 -1
  6. package/dist/mediaplayer/players/html5.js +767 -0
  7. package/dist/mediaplayer/players/youtube.js +470 -0
  8. package/dist/mediaplayer/players.js +35 -0
  9. package/dist/mediaplayer/support.js +134 -0
  10. package/dist/mediaplayer/utils/reminder.js +198 -0
  11. package/dist/mediaplayer/utils/timeObserver.js +149 -0
  12. package/dist/mediaplayer/youtubeManager.js +177 -0
  13. package/dist/mediaplayer.js +1251 -1912
  14. package/dist/previewer.js +25 -19
  15. package/package.json +1 -1
  16. package/scss/basic.scss +1 -0
  17. package/scss/inc/_jquery.nouislider.scss +254 -0
  18. package/src/ckeditor/ckConfigurator.js +10 -1
  19. package/src/itemButtonList/css/item-button-list.css +225 -0
  20. package/src/itemButtonList/css/item-button-list.css.map +1 -0
  21. package/src/mediaEditor/mediaEditorComponent.js +25 -26
  22. package/src/mediaEditor/plugins/mediaDimension/mediaDimensionComponent.js +83 -63
  23. package/src/mediaplayer/css/player.css +104 -14
  24. package/src/mediaplayer/css/player.css.map +1 -1
  25. package/src/mediaplayer/players/html5.js +564 -0
  26. package/src/mediaplayer/players/youtube.js +323 -0
  27. package/src/mediaplayer/players.js +29 -0
  28. package/src/mediaplayer/scss/player.scss +125 -16
  29. package/src/mediaplayer/support.js +126 -0
  30. package/src/mediaplayer/tpl/audio.tpl +6 -0
  31. package/src/mediaplayer/tpl/player.tpl +11 -32
  32. package/src/mediaplayer/tpl/source.tpl +1 -0
  33. package/src/mediaplayer/tpl/video.tpl +6 -0
  34. package/src/mediaplayer/tpl/youtube.tpl +1 -0
  35. package/src/mediaplayer/utils/reminder.js +184 -0
  36. package/src/mediaplayer/utils/timeObserver.js +143 -0
  37. package/src/mediaplayer/youtubeManager.js +161 -0
  38. package/src/mediaplayer.js +1217 -1901
  39. package/src/previewer.js +40 -33
  40. package/src/searchModal/css/advancedSearch.css +190 -0
  41. package/src/searchModal/css/advancedSearch.css.map +1 -0
  42. package/src/searchModal/css/searchModal.css +506 -0
  43. 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
+ });