@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,767 @@
|
|
|
1
|
+
define(['jquery', 'util/urlParser', 'core/eventifier', 'ui/mediaplayer/support', 'handlebars', 'i18n', 'lodash', 'lib/dompurify/purify', 'ui/mediaplayer/utils/reminder', 'ui/mediaplayer/utils/timeObserver'], function ($$1, UrlParser, eventifier, support, Handlebars, __, _, DOMPurify, reminderManagerFactory, timeObserverFactory) { 'use strict';
|
|
2
|
+
|
|
3
|
+
$$1 = $$1 && $$1.hasOwnProperty('default') ? $$1['default'] : $$1;
|
|
4
|
+
UrlParser = UrlParser && UrlParser.hasOwnProperty('default') ? UrlParser['default'] : UrlParser;
|
|
5
|
+
eventifier = eventifier && eventifier.hasOwnProperty('default') ? eventifier['default'] : eventifier;
|
|
6
|
+
support = support && support.hasOwnProperty('default') ? support['default'] : support;
|
|
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
|
+
reminderManagerFactory = reminderManagerFactory && reminderManagerFactory.hasOwnProperty('default') ? reminderManagerFactory['default'] : reminderManagerFactory;
|
|
12
|
+
timeObserverFactory = timeObserverFactory && timeObserverFactory.hasOwnProperty('default') ? timeObserverFactory['default'] : timeObserverFactory;
|
|
13
|
+
|
|
14
|
+
function _typeof(obj) {
|
|
15
|
+
"@babel/helpers - typeof";
|
|
16
|
+
|
|
17
|
+
if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
|
|
18
|
+
_typeof = function (obj) {
|
|
19
|
+
return typeof obj;
|
|
20
|
+
};
|
|
21
|
+
} else {
|
|
22
|
+
_typeof = function (obj) {
|
|
23
|
+
return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return _typeof(obj);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function Helpers0 (hb) {
|
|
31
|
+
//register a i18n helper
|
|
32
|
+
hb.registerHelper('__', function (key) {
|
|
33
|
+
return __(key);
|
|
34
|
+
});
|
|
35
|
+
/**
|
|
36
|
+
* Register dompurify helper
|
|
37
|
+
*
|
|
38
|
+
* https://github.com/cure53/DOMPurify
|
|
39
|
+
* with config SAFE_FOR_TEMPLATES: true
|
|
40
|
+
* to make output safe for template systems
|
|
41
|
+
*/
|
|
42
|
+
|
|
43
|
+
hb.registerHelper('dompurify', function (context) {
|
|
44
|
+
return DOMPurify.sanitize(context);
|
|
45
|
+
});
|
|
46
|
+
/**
|
|
47
|
+
* Register join helper
|
|
48
|
+
*
|
|
49
|
+
* Example :
|
|
50
|
+
* var values = {a:v1, b:v2, c:v3};
|
|
51
|
+
* Using {{{join attributes '=' ' ' '"'}}} will return : a="v1" b="v2" c="v3"
|
|
52
|
+
* Using {{{join values null ' or ' '*'}}} will return : *v1* or *v2* or *v3*
|
|
53
|
+
*/
|
|
54
|
+
|
|
55
|
+
hb.registerHelper('join', function (arr, keyValueGlue, fragmentGlue, wrapper) {
|
|
56
|
+
var fragments = [];
|
|
57
|
+
keyValueGlue = typeof keyValueGlue === 'string' ? keyValueGlue : undefined;
|
|
58
|
+
fragmentGlue = typeof fragmentGlue === 'string' ? fragmentGlue : ' ';
|
|
59
|
+
wrapper = typeof wrapper === 'string' ? wrapper : '"';
|
|
60
|
+
|
|
61
|
+
_.forIn(arr, function (value, key) {
|
|
62
|
+
var fragment = '';
|
|
63
|
+
|
|
64
|
+
if (value !== null || value !== undefined) {
|
|
65
|
+
if (typeof value === 'boolean') {
|
|
66
|
+
value = value ? 'true' : 'false';
|
|
67
|
+
} else if (_typeof(value) === 'object') {
|
|
68
|
+
value = _.values(value).join(' ');
|
|
69
|
+
}
|
|
70
|
+
} else {
|
|
71
|
+
value = '';
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (keyValueGlue !== undefined) {
|
|
75
|
+
fragment += key + keyValueGlue;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
fragment += wrapper + value + wrapper;
|
|
79
|
+
fragments.push(fragment);
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
return fragments.join(fragmentGlue);
|
|
83
|
+
}); //register a classic "for loop" helper
|
|
84
|
+
//it also adds a local variable "i" as the index in each iteration loop
|
|
85
|
+
|
|
86
|
+
hb.registerHelper('for', function (startIndex, stopIndex, increment, options) {
|
|
87
|
+
var ret = '';
|
|
88
|
+
startIndex = parseInt(startIndex);
|
|
89
|
+
stopIndex = parseInt(stopIndex);
|
|
90
|
+
increment = parseInt(increment);
|
|
91
|
+
|
|
92
|
+
for (var i = startIndex; i < stopIndex; i += increment) {
|
|
93
|
+
ret += options.fn(_.extend({}, this, {
|
|
94
|
+
i: i
|
|
95
|
+
}));
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return ret;
|
|
99
|
+
});
|
|
100
|
+
hb.registerHelper('equal', function (var1, var2, options) {
|
|
101
|
+
if (var1 == var2) {
|
|
102
|
+
return options.fn(this);
|
|
103
|
+
} else {
|
|
104
|
+
return options.inverse(this);
|
|
105
|
+
}
|
|
106
|
+
}); // register a "get property" helper
|
|
107
|
+
// it gets the named property from the provided context
|
|
108
|
+
|
|
109
|
+
hb.registerHelper('property', function (name, context) {
|
|
110
|
+
return context[name] || '';
|
|
111
|
+
}); // register an 'includes' helper
|
|
112
|
+
// it checks if value is in array
|
|
113
|
+
|
|
114
|
+
hb.registerHelper('includes', function (haystack, needle, options) {
|
|
115
|
+
if (_.contains(haystack, needle)) {
|
|
116
|
+
return options.fn(this);
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
if (!Helpers0.__initialized) {
|
|
122
|
+
Helpers0(Handlebars);
|
|
123
|
+
Helpers0.__initialized = true;
|
|
124
|
+
}
|
|
125
|
+
var Template = Handlebars.template(function (Handlebars,depth0,helpers,partials,data) {
|
|
126
|
+
this.compilerInfo = [4,'>= 1.0.0'];
|
|
127
|
+
helpers = this.merge(helpers, Handlebars.helpers); data = data || {};
|
|
128
|
+
var buffer = "", stack1, helper, options, functionType="function", escapeExpression=this.escapeExpression, helperMissing=helpers.helperMissing, self=this;
|
|
129
|
+
|
|
130
|
+
function program1(depth0,data) {
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
return "crossorigin";
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function program3(depth0,data) {
|
|
137
|
+
|
|
138
|
+
var buffer = "", stack1, helper, options;
|
|
139
|
+
buffer += "\n <a href=\"";
|
|
140
|
+
if (helper = helpers.link) { stack1 = helper.call(depth0, {hash:{},data:data}); }
|
|
141
|
+
else { helper = (depth0 && depth0.link); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
|
|
142
|
+
buffer += escapeExpression(stack1)
|
|
143
|
+
+ "\">"
|
|
144
|
+
+ escapeExpression((helper = helpers.__ || (depth0 && depth0.__),options={hash:{},data:data},helper ? helper.call(depth0, "Please download the track and listen offline.", options) : helperMissing.call(depth0, "__", "Please download the track and listen offline.", options)))
|
|
145
|
+
+ "</a>\n";
|
|
146
|
+
return buffer;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
buffer += "<audio class=\"media audio\" preload=\"";
|
|
150
|
+
if (helper = helpers.preload) { stack1 = helper.call(depth0, {hash:{},data:data}); }
|
|
151
|
+
else { helper = (depth0 && depth0.preload); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
|
|
152
|
+
buffer += escapeExpression(stack1)
|
|
153
|
+
+ "\" controls ";
|
|
154
|
+
stack1 = helpers['if'].call(depth0, (depth0 && depth0.cors), {hash:{},inverse:self.noop,fn:self.program(1, program1, data),data:data});
|
|
155
|
+
if(stack1 || stack1 === 0) { buffer += stack1; }
|
|
156
|
+
buffer += ">\n "
|
|
157
|
+
+ escapeExpression((helper = helpers.__ || (depth0 && depth0.__),options={hash:{},data:data},helper ? helper.call(depth0, "Your browser doesn’t support the audio player.", options) : helperMissing.call(depth0, "__", "Your browser doesn’t support the audio player.", options)))
|
|
158
|
+
+ "\n";
|
|
159
|
+
stack1 = helpers['if'].call(depth0, (depth0 && depth0.link), {hash:{},inverse:self.noop,fn:self.program(3, program3, data),data:data});
|
|
160
|
+
if(stack1 || stack1 === 0) { buffer += stack1; }
|
|
161
|
+
buffer += "\n</audio>\n";
|
|
162
|
+
return buffer;
|
|
163
|
+
});
|
|
164
|
+
function audioTpl(data, options, asString) {
|
|
165
|
+
var html = Template(data, options);
|
|
166
|
+
return (asString || true) ? html : $(html);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
if (!Helpers0.__initialized) {
|
|
170
|
+
Helpers0(Handlebars);
|
|
171
|
+
Helpers0.__initialized = true;
|
|
172
|
+
}
|
|
173
|
+
var Template$1 = Handlebars.template(function (Handlebars,depth0,helpers,partials,data) {
|
|
174
|
+
this.compilerInfo = [4,'>= 1.0.0'];
|
|
175
|
+
helpers = this.merge(helpers, Handlebars.helpers); data = data || {};
|
|
176
|
+
var buffer = "", stack1, helper, options, functionType="function", escapeExpression=this.escapeExpression, helperMissing=helpers.helperMissing, self=this;
|
|
177
|
+
|
|
178
|
+
function program1(depth0,data) {
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
return "crossorigin";
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
function program3(depth0,data) {
|
|
185
|
+
|
|
186
|
+
var buffer = "", stack1, helper, options;
|
|
187
|
+
buffer += "\n <a href=\"";
|
|
188
|
+
if (helper = helpers.link) { stack1 = helper.call(depth0, {hash:{},data:data}); }
|
|
189
|
+
else { helper = (depth0 && depth0.link); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
|
|
190
|
+
buffer += escapeExpression(stack1)
|
|
191
|
+
+ "\">"
|
|
192
|
+
+ escapeExpression((helper = helpers.__ || (depth0 && depth0.__),options={hash:{},data:data},helper ? helper.call(depth0, "Please download the video and view offline.", options) : helperMissing.call(depth0, "__", "Please download the video and view offline.", options)))
|
|
193
|
+
+ "</a>\n";
|
|
194
|
+
return buffer;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
buffer += "<video class=\"media video\" preload=\"";
|
|
198
|
+
if (helper = helpers.preload) { stack1 = helper.call(depth0, {hash:{},data:data}); }
|
|
199
|
+
else { helper = (depth0 && depth0.preload); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
|
|
200
|
+
buffer += escapeExpression(stack1)
|
|
201
|
+
+ "\" poster=\"";
|
|
202
|
+
if (helper = helpers.poster) { stack1 = helper.call(depth0, {hash:{},data:data}); }
|
|
203
|
+
else { helper = (depth0 && depth0.poster); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
|
|
204
|
+
buffer += escapeExpression(stack1)
|
|
205
|
+
+ "\" controls ";
|
|
206
|
+
stack1 = helpers['if'].call(depth0, (depth0 && depth0.cors), {hash:{},inverse:self.noop,fn:self.program(1, program1, data),data:data});
|
|
207
|
+
if(stack1 || stack1 === 0) { buffer += stack1; }
|
|
208
|
+
buffer += ">\n "
|
|
209
|
+
+ escapeExpression((helper = helpers.__ || (depth0 && depth0.__),options={hash:{},data:data},helper ? helper.call(depth0, "Your browser doesn’t support the video player.", options) : helperMissing.call(depth0, "__", "Your browser doesn’t support the video player.", options)))
|
|
210
|
+
+ "\n";
|
|
211
|
+
stack1 = helpers['if'].call(depth0, (depth0 && depth0.link), {hash:{},inverse:self.noop,fn:self.program(3, program3, data),data:data});
|
|
212
|
+
if(stack1 || stack1 === 0) { buffer += stack1; }
|
|
213
|
+
buffer += "\n</video>\n";
|
|
214
|
+
return buffer;
|
|
215
|
+
});
|
|
216
|
+
function videoTpl(data, options, asString) {
|
|
217
|
+
var html = Template$1(data, options);
|
|
218
|
+
return (asString || true) ? html : $(html);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
if (!Helpers0.__initialized) {
|
|
222
|
+
Helpers0(Handlebars);
|
|
223
|
+
Helpers0.__initialized = true;
|
|
224
|
+
}
|
|
225
|
+
var Template$2 = Handlebars.template(function (Handlebars,depth0,helpers,partials,data) {
|
|
226
|
+
this.compilerInfo = [4,'>= 1.0.0'];
|
|
227
|
+
helpers = this.merge(helpers, Handlebars.helpers); data = data || {};
|
|
228
|
+
var buffer = "", stack1, helper, functionType="function", escapeExpression=this.escapeExpression;
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
buffer += "<source src=\"";
|
|
232
|
+
if (helper = helpers.src) { stack1 = helper.call(depth0, {hash:{},data:data}); }
|
|
233
|
+
else { helper = (depth0 && depth0.src); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
|
|
234
|
+
buffer += escapeExpression(stack1)
|
|
235
|
+
+ "\" type=\"";
|
|
236
|
+
if (helper = helpers.type) { stack1 = helper.call(depth0, {hash:{},data:data}); }
|
|
237
|
+
else { helper = (depth0 && depth0.type); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
|
|
238
|
+
buffer += escapeExpression(stack1)
|
|
239
|
+
+ "\">\n";
|
|
240
|
+
return buffer;
|
|
241
|
+
});
|
|
242
|
+
function sourceTpl(data, options, asString) {
|
|
243
|
+
var html = Template$2(data, options);
|
|
244
|
+
return (asString || true) ? html : $(html);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* This program is free software; you can redistribute it and/or
|
|
249
|
+
* modify it under the terms of the GNU General Public License
|
|
250
|
+
* as published by the Free Software Foundation; under version 2
|
|
251
|
+
* of the License (non-upgradable).
|
|
252
|
+
*
|
|
253
|
+
* This program is distributed in the hope that it will be useful,
|
|
254
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
255
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
256
|
+
* GNU General Public License for more details.
|
|
257
|
+
*
|
|
258
|
+
* You should have received a copy of the GNU General Public License
|
|
259
|
+
* along with this program; if not, write to the Free Software
|
|
260
|
+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
261
|
+
*
|
|
262
|
+
* Copyright (c) 2015-2021 (original work) Open Assessment Technologies SA ;
|
|
263
|
+
*/
|
|
264
|
+
/**
|
|
265
|
+
* CSS namespace
|
|
266
|
+
* @type {string}
|
|
267
|
+
*/
|
|
268
|
+
|
|
269
|
+
var ns = '.mediaplayer';
|
|
270
|
+
/**
|
|
271
|
+
* Range value of the volume
|
|
272
|
+
* @type {number}
|
|
273
|
+
*/
|
|
274
|
+
|
|
275
|
+
var volumeRange = 100;
|
|
276
|
+
/**
|
|
277
|
+
* Delay before considering a media stalled
|
|
278
|
+
* @type {number}
|
|
279
|
+
*/
|
|
280
|
+
|
|
281
|
+
var stalledDetectionDelay = 2000;
|
|
282
|
+
/**
|
|
283
|
+
* List of media events that can be listened to for debugging
|
|
284
|
+
* @type {string[]}
|
|
285
|
+
*/
|
|
286
|
+
|
|
287
|
+
var mediaEvents = ['abort', 'canplay', 'canplaythrough', 'canshowcurrentframe', 'dataunavailable', 'durationchange', 'emptied', 'empty', 'ended', 'error', 'loadeddata', 'loadedfirstframe', 'loadedmetadata', 'loadstart', 'pause', 'play', 'playing', 'progress', 'ratechange', 'seeked', 'seeking', 'stalled', 'suspend', 'timeupdate', 'volumechange', 'waiting'];
|
|
288
|
+
/**
|
|
289
|
+
* List of player events that can be listened to for debugging
|
|
290
|
+
* @type {string[]}
|
|
291
|
+
*/
|
|
292
|
+
|
|
293
|
+
var playerEvents = ['end', 'error', 'pause', 'play', 'playing', 'ready', 'resize', 'stalled', 'timeupdate'];
|
|
294
|
+
/**
|
|
295
|
+
* Defines a player object dedicated to the native HTML5 player
|
|
296
|
+
* @param {jQuery} $container - Where to render the player
|
|
297
|
+
* @param {object} config - The list of config entries
|
|
298
|
+
* @param {Array} config.sources - The list of media sources
|
|
299
|
+
* @param {string} [config.type] - The type of player (video or audio) (default: video)
|
|
300
|
+
* @param {boolean} [config.preview] - Enables the media preview (load media metadata)
|
|
301
|
+
* @param {boolean} [config.debug] - Enables the debug mode
|
|
302
|
+
* @param {number} [config.config.stalledDetectionDelay] - The delay before considering a media is stalled
|
|
303
|
+
* @returns {object} player
|
|
304
|
+
*/
|
|
305
|
+
|
|
306
|
+
function html5PlayerFactory($container) {
|
|
307
|
+
var config = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
308
|
+
var type = config.type || 'video';
|
|
309
|
+
var sources = config.sources || [];
|
|
310
|
+
var updateObserver = reminderManagerFactory();
|
|
311
|
+
var timeObserver = timeObserverFactory();
|
|
312
|
+
config.stalledDetectionDelay = config.stalledDetectionDelay || stalledDetectionDelay;
|
|
313
|
+
var $media;
|
|
314
|
+
var media;
|
|
315
|
+
var state = {};
|
|
316
|
+
|
|
317
|
+
var getDebugContext = function getDebugContext(action) {
|
|
318
|
+
var networkState = media && media.networkState;
|
|
319
|
+
var readyState = media && media.readyState;
|
|
320
|
+
return "[html5-".concat(type, "(networkState=").concat(networkState, ",readyState=").concat(readyState, "):").concat(action, "]");
|
|
321
|
+
}; // eslint-disable-next-line
|
|
322
|
+
|
|
323
|
+
|
|
324
|
+
var debug = function debug(action) {
|
|
325
|
+
var _window$console;
|
|
326
|
+
|
|
327
|
+
for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
|
|
328
|
+
args[_key - 1] = arguments[_key];
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
return (config.debug === true || config.debug === action) && (_window$console = window.console).log.apply(_window$console, [getDebugContext(action)].concat(args));
|
|
332
|
+
};
|
|
333
|
+
|
|
334
|
+
return eventifier({
|
|
335
|
+
init: function init() {
|
|
336
|
+
var _this = this;
|
|
337
|
+
|
|
338
|
+
var tpl = 'audio' === type ? audioTpl : videoTpl;
|
|
339
|
+
var page = new UrlParser(window.location);
|
|
340
|
+
var cors = false;
|
|
341
|
+
var preload = config.preview ? 'metadata' : 'none';
|
|
342
|
+
var poster = '';
|
|
343
|
+
var link = '';
|
|
344
|
+
var result = false;
|
|
345
|
+
state = {};
|
|
346
|
+
sources.forEach(function (source) {
|
|
347
|
+
if (!page.sameDomain(source.src)) {
|
|
348
|
+
cors = true;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
if (source.poster) {
|
|
352
|
+
poster = source.poster;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
if (source.link) {
|
|
356
|
+
link = source.link;
|
|
357
|
+
}
|
|
358
|
+
});
|
|
359
|
+
$media = $$1(tpl({
|
|
360
|
+
cors: cors,
|
|
361
|
+
preload: preload,
|
|
362
|
+
poster: poster,
|
|
363
|
+
link: link
|
|
364
|
+
}));
|
|
365
|
+
$container.append($media);
|
|
366
|
+
media = $media.get(0);
|
|
367
|
+
result = !!(media && support.checkSupport(media)); // Remove the browser native controls if we can use the API instead
|
|
368
|
+
|
|
369
|
+
if (support.canControl()) {
|
|
370
|
+
$media.removeAttr('controls');
|
|
371
|
+
} // Detect stalled video when the timer suddenly jump to the end
|
|
372
|
+
|
|
373
|
+
|
|
374
|
+
timeObserver.removeAllListeners().on('irregularity', function (position) {
|
|
375
|
+
if (state.playback && state.stallDetection) {
|
|
376
|
+
_this.stalled(position);
|
|
377
|
+
}
|
|
378
|
+
});
|
|
379
|
+
$media.on("play".concat(ns), function () {
|
|
380
|
+
state.playback = true;
|
|
381
|
+
state.playedViaApi = false;
|
|
382
|
+
timeObserver.init(media.currentTime, media.duration);
|
|
383
|
+
|
|
384
|
+
_this.trigger('play');
|
|
385
|
+
}).on("pause".concat(ns), function () {
|
|
386
|
+
if (state.stallDetection && !state.pausedViaApi && updateObserver.running && updateObserver.elapsed < 100) {
|
|
387
|
+
// The pause event may be triggered after a connectivity issue as the player is out of data
|
|
388
|
+
_this.stalled();
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
state.pausedViaApi = false;
|
|
392
|
+
state.playing = false;
|
|
393
|
+
updateObserver.stop();
|
|
394
|
+
|
|
395
|
+
_this.trigger('pause');
|
|
396
|
+
}).on("seeked".concat(ns), function () {
|
|
397
|
+
// When the user try changing the current playing position while the network is down,
|
|
398
|
+
// the player will end the playback by moving straight to the end.
|
|
399
|
+
if (state.seekedViaApi && Math.floor(state.seekAt) !== Math.floor(media.currentTime)) {
|
|
400
|
+
state.stallDetection = true;
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
state.seekedViaApi = false;
|
|
404
|
+
}).on("ended".concat(ns), function () {
|
|
405
|
+
updateObserver.forget().stop();
|
|
406
|
+
timeObserver.update(media.currentTime);
|
|
407
|
+
state.playback = false;
|
|
408
|
+
state.playing = false;
|
|
409
|
+
|
|
410
|
+
_this.trigger('end');
|
|
411
|
+
}).on("timeupdate".concat(ns), function () {
|
|
412
|
+
state.playing = true;
|
|
413
|
+
updateObserver.start();
|
|
414
|
+
timeObserver.update(media.currentTime);
|
|
415
|
+
|
|
416
|
+
_this.trigger('timeupdate');
|
|
417
|
+
}).on('loadstart', function () {
|
|
418
|
+
if (media.networkState === HTMLMediaElement.NETWORK_NO_SOURCE) {
|
|
419
|
+
_this.trigger('error');
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
if (!config.preview && media.networkState === HTMLMediaElement.NETWORK_IDLE) {
|
|
423
|
+
_this.trigger('ready');
|
|
424
|
+
} // The media may be unreachable straight from the beginning
|
|
425
|
+
|
|
426
|
+
|
|
427
|
+
_this.detectStalledNetwork();
|
|
428
|
+
}).on("waiting".concat(ns), function () {
|
|
429
|
+
// The "waiting" event means the player is pending data,
|
|
430
|
+
// it may be the symptom of a connectivity issue
|
|
431
|
+
_this.detectStalledNetwork();
|
|
432
|
+
}).on("error".concat(ns), function () {
|
|
433
|
+
if (media.networkState === HTMLMediaElement.NETWORK_NO_SOURCE || media.error instanceof MediaError && media.error.code === MediaError.MEDIA_ERR_SRC_NOT_SUPPORTED) {
|
|
434
|
+
// No source means the player does not support the supplied media.
|
|
435
|
+
// Or it can be more explicit with the not supported error.
|
|
436
|
+
// There is nothing that we can do from this stage.
|
|
437
|
+
_this.trigger('error');
|
|
438
|
+
} else {
|
|
439
|
+
// Other errors need special attention as they can be recoverable
|
|
440
|
+
_this.handleError(media.error);
|
|
441
|
+
}
|
|
442
|
+
}).on('loadedmetadata', function () {
|
|
443
|
+
timeObserver.init(media.currentTime, media.duration);
|
|
444
|
+
|
|
445
|
+
_this.ready();
|
|
446
|
+
}).on("canplay".concat(ns), function () {
|
|
447
|
+
if (!state.stalled) {
|
|
448
|
+
_this.ready();
|
|
449
|
+
}
|
|
450
|
+
}).on("stalled".concat(ns), function () {
|
|
451
|
+
// The "stalled" event may be triggered once the player is halted after initialisation,
|
|
452
|
+
// but this does not mean the playback is actually stalled, hence we only take care of the playing state
|
|
453
|
+
if (state.playing && !media.paused) {
|
|
454
|
+
_this.handleError(media.error);
|
|
455
|
+
}
|
|
456
|
+
}).on("playing".concat(ns), function () {
|
|
457
|
+
if (state.stallDetection) {
|
|
458
|
+
// The "playing" event may occur after a connectivity issue.
|
|
459
|
+
// For the sake of the stall detection, we need to discard this event
|
|
460
|
+
return;
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
updateObserver.forget().start();
|
|
464
|
+
state.playing = true;
|
|
465
|
+
|
|
466
|
+
_this.trigger('playing');
|
|
467
|
+
}); // install debug logger
|
|
468
|
+
|
|
469
|
+
if (config.debug) {
|
|
470
|
+
debug('installed', media);
|
|
471
|
+
mediaEvents.forEach(function (eventName) {
|
|
472
|
+
$media.on(eventName + ns, function (e) {
|
|
473
|
+
return debug('media event', eventName, media && media.currentSrc, e);
|
|
474
|
+
});
|
|
475
|
+
});
|
|
476
|
+
playerEvents.forEach(function (eventName) {
|
|
477
|
+
_this.on(eventName, function () {
|
|
478
|
+
for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
|
|
479
|
+
args[_key2] = arguments[_key2];
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
return debug.apply(void 0, ['player event', eventName, media && media.currentSrc].concat(args));
|
|
483
|
+
});
|
|
484
|
+
});
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
result = result && sources.reduce(function (supported, source) {
|
|
488
|
+
return _this.addMedia(source.src, source.type) || supported;
|
|
489
|
+
}, false);
|
|
490
|
+
return result;
|
|
491
|
+
},
|
|
492
|
+
handleError: function handleError(error) {
|
|
493
|
+
var _this2 = this;
|
|
494
|
+
|
|
495
|
+
// Discard legitimate and non-blocking errors
|
|
496
|
+
switch (error && error.name) {
|
|
497
|
+
case 'NotAllowedError':
|
|
498
|
+
debug('api call', 'handleError', 'the autoplay is not allowed without a user interaction', error);
|
|
499
|
+
return;
|
|
500
|
+
|
|
501
|
+
case 'AbortError':
|
|
502
|
+
debug('api call', 'handleError', 'the action has been aborted for some reason', error);
|
|
503
|
+
return;
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
debug('api call', 'handleError', error); // Detect if the playback can continue a bit
|
|
507
|
+
|
|
508
|
+
var canContinueTemporarily = media && (media.readyState === HTMLMediaElement.HAVE_ENOUGH_DATA || media.readyState === HTMLMediaElement.HAVE_FUTURE_DATA || media.readyState === HTMLMediaElement.HAVE_CURRENT_DATA); // If a connectivity error occurs we may need to enter in stalled mode unless we can wait a bit
|
|
509
|
+
|
|
510
|
+
if (error instanceof MediaError && (error.code === MediaError.MEDIA_ERR_NETWORK || error.code === MediaError.MEDIA_ERR_DECODE) && !canContinueTemporarily) {
|
|
511
|
+
this.stalled();
|
|
512
|
+
return;
|
|
513
|
+
} // To this point, there is a big chance the media is stalled.
|
|
514
|
+
// We start an observer to remind as soon as an irregularity occurs on the time update
|
|
515
|
+
|
|
516
|
+
|
|
517
|
+
state.stallDetection = true;
|
|
518
|
+
updateObserver.remind(function () {
|
|
519
|
+
// The last time update is a bit old, the media is most probably stalled now
|
|
520
|
+
if (updateObserver.elapsed >= config.stalledDetectionDelay) {
|
|
521
|
+
_this2.stalled();
|
|
522
|
+
}
|
|
523
|
+
}, config.stalledDetectionDelay);
|
|
524
|
+
updateObserver.start();
|
|
525
|
+
},
|
|
526
|
+
ready: function ready() {
|
|
527
|
+
if (!state.ready) {
|
|
528
|
+
state.ready = true;
|
|
529
|
+
this.trigger('ready');
|
|
530
|
+
}
|
|
531
|
+
},
|
|
532
|
+
detectStalledNetwork: function detectStalledNetwork() {
|
|
533
|
+
var _this3 = this;
|
|
534
|
+
|
|
535
|
+
// Install an observer that will watch the network state after a small delay.
|
|
536
|
+
// It is needed since the network state may need time to settle.
|
|
537
|
+
setTimeout(function () {
|
|
538
|
+
if (media && media.networkState === HTMLMediaElement.NETWORK_NO_SOURCE && media.readyState === HTMLMediaElement.HAVE_NOTHING) {
|
|
539
|
+
if (!state.ready) {
|
|
540
|
+
_this3.trigger('ready');
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
_this3.stalled();
|
|
544
|
+
}
|
|
545
|
+
}, config.stalledDetectionDelay);
|
|
546
|
+
},
|
|
547
|
+
stalled: function stalled(position) {
|
|
548
|
+
debug('api call', 'stalled');
|
|
549
|
+
|
|
550
|
+
if (media) {
|
|
551
|
+
if ('undefined' !== typeof position) {
|
|
552
|
+
state.stalledAt = position;
|
|
553
|
+
} else {
|
|
554
|
+
state.stalledAt = timeObserver.position;
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
state.stalled = true;
|
|
559
|
+
state.stallDetection = false;
|
|
560
|
+
updateObserver.forget().stop();
|
|
561
|
+
this.pause();
|
|
562
|
+
this.trigger('stalled');
|
|
563
|
+
},
|
|
564
|
+
recover: function recover() {
|
|
565
|
+
debug('api call', 'recover');
|
|
566
|
+
state.stalled = false;
|
|
567
|
+
state.stallDetection = false;
|
|
568
|
+
|
|
569
|
+
if (media) {
|
|
570
|
+
// Special processing of video player to prevent visual glitch while reloading
|
|
571
|
+
if (media.tagName === 'VIDEO') {
|
|
572
|
+
// Temporarily set the size of the media to prevent a shrink while reloading it
|
|
573
|
+
$media.width($media.width());
|
|
574
|
+
$media.height($media.height());
|
|
575
|
+
$media.on('loadedmetadata.recover', function () {
|
|
576
|
+
$media.off('loadedmetadata.recover');
|
|
577
|
+
$media.css({
|
|
578
|
+
width: '',
|
|
579
|
+
height: ''
|
|
580
|
+
});
|
|
581
|
+
});
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
media.load();
|
|
585
|
+
|
|
586
|
+
if (state.stalledAt) {
|
|
587
|
+
this.seek(state.stalledAt);
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
if (state.playback && !state.playing || state.playedViaApi) {
|
|
591
|
+
this.play();
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
},
|
|
595
|
+
destroy: function destroy() {
|
|
596
|
+
debug('api call', 'destroy');
|
|
597
|
+
this.stop();
|
|
598
|
+
this.removeAllListeners();
|
|
599
|
+
updateObserver.forget();
|
|
600
|
+
timeObserver.removeAllListeners();
|
|
601
|
+
|
|
602
|
+
if ($media) {
|
|
603
|
+
$media.off(ns).remove();
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
$media = void 0;
|
|
607
|
+
media = void 0;
|
|
608
|
+
state = {};
|
|
609
|
+
},
|
|
610
|
+
getMedia: function getMedia() {
|
|
611
|
+
debug('api call', 'getMedia', media);
|
|
612
|
+
return media;
|
|
613
|
+
},
|
|
614
|
+
getMediaSize: function getMediaSize() {
|
|
615
|
+
var size = {};
|
|
616
|
+
|
|
617
|
+
if (media) {
|
|
618
|
+
size = {
|
|
619
|
+
width: media.videoWidth,
|
|
620
|
+
height: media.videoHeight
|
|
621
|
+
};
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
debug('api call', 'getMediaSize', size);
|
|
625
|
+
return size;
|
|
626
|
+
},
|
|
627
|
+
getPosition: function getPosition() {
|
|
628
|
+
var position = 0;
|
|
629
|
+
|
|
630
|
+
if (media) {
|
|
631
|
+
position = media.currentTime;
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
debug('api call', 'getPosition', position);
|
|
635
|
+
return position;
|
|
636
|
+
},
|
|
637
|
+
getDuration: function getDuration() {
|
|
638
|
+
var duration = 0;
|
|
639
|
+
|
|
640
|
+
if (media) {
|
|
641
|
+
duration = media.duration;
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
debug('api call', 'getDuration', duration);
|
|
645
|
+
return duration;
|
|
646
|
+
},
|
|
647
|
+
getVolume: function getVolume() {
|
|
648
|
+
var volume = 0;
|
|
649
|
+
|
|
650
|
+
if (media) {
|
|
651
|
+
volume = parseFloat(media.volume) * volumeRange;
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
debug('api call', 'getVolume', volume);
|
|
655
|
+
return volume;
|
|
656
|
+
},
|
|
657
|
+
setVolume: function setVolume(volume) {
|
|
658
|
+
debug('api call', 'setVolume', volume);
|
|
659
|
+
|
|
660
|
+
if (media) {
|
|
661
|
+
media.volume = parseFloat(volume) / volumeRange;
|
|
662
|
+
}
|
|
663
|
+
},
|
|
664
|
+
setSize: function setSize(width, height) {
|
|
665
|
+
debug('api call', 'setSize', width, height);
|
|
666
|
+
this.trigger('resize', width, height);
|
|
667
|
+
},
|
|
668
|
+
seek: function seek(time) {
|
|
669
|
+
debug('api call', 'seek', time);
|
|
670
|
+
|
|
671
|
+
if (media) {
|
|
672
|
+
media.currentTime = parseFloat(time);
|
|
673
|
+
state.seekedViaApi = true;
|
|
674
|
+
state.seekAt = media.currentTime;
|
|
675
|
+
timeObserver.seek(media.currentTime);
|
|
676
|
+
|
|
677
|
+
if (!state.playback) {
|
|
678
|
+
this.play();
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
},
|
|
682
|
+
play: function play() {
|
|
683
|
+
var _this4 = this;
|
|
684
|
+
|
|
685
|
+
debug('api call', 'play');
|
|
686
|
+
|
|
687
|
+
if (media) {
|
|
688
|
+
state.playedViaApi = true;
|
|
689
|
+
var startPlayPromise = media.play();
|
|
690
|
+
|
|
691
|
+
if ('undefined' !== typeof startPlayPromise) {
|
|
692
|
+
startPlayPromise.catch(function (error) {
|
|
693
|
+
return _this4.handleError(error);
|
|
694
|
+
});
|
|
695
|
+
}
|
|
696
|
+
}
|
|
697
|
+
},
|
|
698
|
+
pause: function pause() {
|
|
699
|
+
debug('api call', 'pause');
|
|
700
|
+
|
|
701
|
+
if (media) {
|
|
702
|
+
if (!media.paused) {
|
|
703
|
+
state.pausedViaApi = true;
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
media.pause();
|
|
707
|
+
}
|
|
708
|
+
},
|
|
709
|
+
stop: function stop() {
|
|
710
|
+
debug('api call', 'stop');
|
|
711
|
+
|
|
712
|
+
if (media && media.duration && state.playback && !state.stalled) {
|
|
713
|
+
media.currentTime = media.duration;
|
|
714
|
+
}
|
|
715
|
+
},
|
|
716
|
+
mute: function mute(muted) {
|
|
717
|
+
debug('api call', 'mute', muted);
|
|
718
|
+
|
|
719
|
+
if (media) {
|
|
720
|
+
media.muted = !!muted;
|
|
721
|
+
}
|
|
722
|
+
},
|
|
723
|
+
isMuted: function isMuted() {
|
|
724
|
+
var mute = false;
|
|
725
|
+
|
|
726
|
+
if (media) {
|
|
727
|
+
mute = !!media.muted;
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
debug('api call', 'isMuted', mute);
|
|
731
|
+
return mute;
|
|
732
|
+
},
|
|
733
|
+
addMedia: function addMedia(src, srcType) {
|
|
734
|
+
debug('api call', 'addMedia', src, srcType);
|
|
735
|
+
|
|
736
|
+
if (media) {
|
|
737
|
+
if (!support.checkSupport(media, srcType)) {
|
|
738
|
+
return false;
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
if (src && $media) {
|
|
743
|
+
$media.append(sourceTpl({
|
|
744
|
+
src: src,
|
|
745
|
+
type: srcType
|
|
746
|
+
}));
|
|
747
|
+
return true;
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
return false;
|
|
751
|
+
},
|
|
752
|
+
setMedia: function setMedia(src, srcType) {
|
|
753
|
+
debug('api call', 'setMedia', src, srcType);
|
|
754
|
+
|
|
755
|
+
if ($media) {
|
|
756
|
+
$media.empty();
|
|
757
|
+
return this.addMedia(src, srcType);
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
return false;
|
|
761
|
+
}
|
|
762
|
+
});
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
return html5PlayerFactory;
|
|
766
|
+
|
|
767
|
+
});
|