@oat-sa/tao-core-ui 1.6.2 → 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/mediaplayer/css/player.css +34 -2
- package/dist/mediaplayer/css/player.css.map +1 -1
- package/dist/mediaplayer/players/html5.js +236 -59
- package/dist/mediaplayer/support.js +17 -3
- package/dist/mediaplayer/utils/reminder.js +198 -0
- package/dist/mediaplayer/utils/timeObserver.js +149 -0
- package/dist/mediaplayer.js +44 -97
- package/package.json +1 -1
- package/src/itemButtonList/css/item-button-list.css +225 -0
- package/src/itemButtonList/css/item-button-list.css.map +1 -0
- package/src/mediaplayer/css/player.css +34 -2
- package/src/mediaplayer/css/player.css.map +1 -1
- package/src/mediaplayer/players/html5.js +247 -67
- package/src/mediaplayer/scss/player.scss +47 -6
- package/src/mediaplayer/support.js +17 -4
- package/src/mediaplayer/tpl/player.tpl +1 -2
- package/src/mediaplayer/utils/reminder.js +184 -0
- package/src/mediaplayer/utils/timeObserver.js +143 -0
- package/src/mediaplayer.js +38 -88
|
@@ -0,0 +1,198 @@
|
|
|
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) 2021 (original work) Open Assessment Technologies SA ;
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Creates a reminder manager.
|
|
23
|
+
*
|
|
24
|
+
* A reminder manager allows to register callback functions that will be called after a particular amount of time.
|
|
25
|
+
* The schedule can be created and cancelled at any time.
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* // Create a reminder manager
|
|
29
|
+
* const manager = reminderManagerFactory();
|
|
30
|
+
*
|
|
31
|
+
* // Add a reminder that will be called after 2s (delay is given in milliseconds)
|
|
32
|
+
* manager.remind(() => console.log('Hello!'), 2000);
|
|
33
|
+
*
|
|
34
|
+
* // Start the schedule
|
|
35
|
+
* manager.start();
|
|
36
|
+
*
|
|
37
|
+
* // We can know how many time elapsed since the last schedule
|
|
38
|
+
* const elapsed = manager.elapsed;
|
|
39
|
+
*
|
|
40
|
+
* // The schedule can be cancelled
|
|
41
|
+
* if (needToCancel) {
|
|
42
|
+
* manager.stop();
|
|
43
|
+
* }
|
|
44
|
+
*
|
|
45
|
+
* // The schedule should be cancelled
|
|
46
|
+
* console.log('schedule running:', manager.running)
|
|
47
|
+
*
|
|
48
|
+
* @returns {reminderManager}
|
|
49
|
+
*/
|
|
50
|
+
function reminderManagerFactory() {
|
|
51
|
+
// Keep track of the running state
|
|
52
|
+
var running = false; // Timestamp of the last start
|
|
53
|
+
|
|
54
|
+
var last = 0; // A list of reminders to callback
|
|
55
|
+
|
|
56
|
+
var reminders = new Map();
|
|
57
|
+
/**
|
|
58
|
+
* Cancels a schedule for a particular reminder.
|
|
59
|
+
* @param {object} state - A sate object containing the timeout handler for the reminder.
|
|
60
|
+
* @private
|
|
61
|
+
*/
|
|
62
|
+
|
|
63
|
+
var stopReminder = function stopReminder(state) {
|
|
64
|
+
if (state && state.timeout) {
|
|
65
|
+
clearTimeout(state.timeout);
|
|
66
|
+
state.timeout = null;
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
/**
|
|
70
|
+
* Cancel the schedule for all reminders.
|
|
71
|
+
* @private
|
|
72
|
+
*/
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
var stopAllReminders = function stopAllReminders() {
|
|
76
|
+
return reminders.forEach(stopReminder);
|
|
77
|
+
};
|
|
78
|
+
/**
|
|
79
|
+
* Schedule all reminders.
|
|
80
|
+
* @private
|
|
81
|
+
*/
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
var startAllReminders = function startAllReminders() {
|
|
85
|
+
reminders.forEach(function (state, reminder) {
|
|
86
|
+
stopReminder(state);
|
|
87
|
+
state.timeout = setTimeout(reminder, state.delay);
|
|
88
|
+
});
|
|
89
|
+
};
|
|
90
|
+
/**
|
|
91
|
+
* Defines the API of a reminder manager.
|
|
92
|
+
*
|
|
93
|
+
* A reminder manager allows to register callback functions that will be called after a particular amount of time.
|
|
94
|
+
* The schedule can be created and cancelled at any time.
|
|
95
|
+
*
|
|
96
|
+
* @namespace reminderManager
|
|
97
|
+
*/
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
return {
|
|
101
|
+
/**
|
|
102
|
+
* Tells whether or not the schedule is running.
|
|
103
|
+
* @type {boolean}
|
|
104
|
+
* @member running
|
|
105
|
+
* @memberOf reminderManager
|
|
106
|
+
*/
|
|
107
|
+
get running() {
|
|
108
|
+
return running;
|
|
109
|
+
},
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Gives the amount of time elapsed since the start of the schedule. It is given in milliseconds.
|
|
113
|
+
* If the schedule is not running, it will always be 0.
|
|
114
|
+
* @type {number}
|
|
115
|
+
* @member running
|
|
116
|
+
* @memberOf reminderManager
|
|
117
|
+
*/
|
|
118
|
+
get elapsed() {
|
|
119
|
+
if (!running) {
|
|
120
|
+
return 0;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return performance.now() - last;
|
|
124
|
+
},
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Schedules all reminders from now on.
|
|
128
|
+
*
|
|
129
|
+
* @returns {reminderManager}
|
|
130
|
+
* @function start
|
|
131
|
+
* @memberOf reminderManager
|
|
132
|
+
*/
|
|
133
|
+
start: function start() {
|
|
134
|
+
running = true;
|
|
135
|
+
last = performance.now();
|
|
136
|
+
startAllReminders();
|
|
137
|
+
return this;
|
|
138
|
+
},
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Cancels all scheduled reminders.
|
|
142
|
+
*
|
|
143
|
+
* @returns {reminderManager}
|
|
144
|
+
* @function stop
|
|
145
|
+
* @memberOf reminderManager
|
|
146
|
+
*/
|
|
147
|
+
stop: function stop() {
|
|
148
|
+
running = false;
|
|
149
|
+
stopAllReminders();
|
|
150
|
+
return this;
|
|
151
|
+
},
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Adds a callback to be scheduled.
|
|
155
|
+
* It won't be scheduled until the schedule is restarted.
|
|
156
|
+
*
|
|
157
|
+
* @param {Function} cb - A function to call after the delay elapsed.
|
|
158
|
+
* @param {number} delay - The delay after what call back the reminder. It is given in milliseconds.
|
|
159
|
+
* @returns {reminderManager}
|
|
160
|
+
* @function remind
|
|
161
|
+
* @memberOf reminderManager
|
|
162
|
+
*/
|
|
163
|
+
remind: function remind(cb, delay) {
|
|
164
|
+
if ('function' === typeof cb && delay) {
|
|
165
|
+
stopReminder(reminders.get(cb));
|
|
166
|
+
reminders.set(cb, {
|
|
167
|
+
delay: delay
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
return this;
|
|
172
|
+
},
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Removes a scheduled callback. If a schedule was running, it will be cancelled first.
|
|
176
|
+
*
|
|
177
|
+
* @param {Function} [cb] - The callback function to remove. If omitted, all reminders will be removed.
|
|
178
|
+
* @returns {reminderManager}
|
|
179
|
+
* @function forget
|
|
180
|
+
* @memberOf reminderManager
|
|
181
|
+
*/
|
|
182
|
+
forget: function forget(cb) {
|
|
183
|
+
if ('undefined' !== typeof cb) {
|
|
184
|
+
stopReminder(reminders.get(cb));
|
|
185
|
+
reminders.delete(cb);
|
|
186
|
+
} else {
|
|
187
|
+
stopAllReminders();
|
|
188
|
+
reminders.clear();
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
return this;
|
|
192
|
+
}
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
return reminderManagerFactory;
|
|
197
|
+
|
|
198
|
+
});
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
define(['core/eventifier'], function (eventifier) { 'use strict';
|
|
2
|
+
|
|
3
|
+
eventifier = eventifier && eventifier.hasOwnProperty('default') ? eventifier['default'] : eventifier;
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* This program is free software; you can redistribute it and/or
|
|
7
|
+
* modify it under the terms of the GNU General Public License
|
|
8
|
+
* as published by the Free Software Foundation; under version 2
|
|
9
|
+
* of the License (non-upgradable).
|
|
10
|
+
*
|
|
11
|
+
* This program is distributed in the hope that it will be useful,
|
|
12
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
13
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
14
|
+
* GNU General Public License for more details.
|
|
15
|
+
*
|
|
16
|
+
* You should have received a copy of the GNU General Public License
|
|
17
|
+
* along with this program; if not, write to the Free Software
|
|
18
|
+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
19
|
+
*
|
|
20
|
+
* Copyright (c) 2021 (original work) Open Assessment Technologies SA ;
|
|
21
|
+
*/
|
|
22
|
+
/**
|
|
23
|
+
* Creates a time observer.
|
|
24
|
+
*
|
|
25
|
+
* It observes the updates applied to a timeline, raising a flag when an irregularity occurs.
|
|
26
|
+
*
|
|
27
|
+
* It works as follow:
|
|
28
|
+
* - an initial state is defined (example: current: 0, duration: 100)
|
|
29
|
+
* - each time a position is forced (say the position is changed outside of the regular time update), the observer needs
|
|
30
|
+
* to be notified.
|
|
31
|
+
* - each time the position is updated (say regular time update), the observer needs to be called.
|
|
32
|
+
* - if the difference between the last regular update and the last one is too high, an event is triggered
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* // Create a time observer with an expected interval of 2 seconds
|
|
36
|
+
* const observer = timeObserverFactory(2);
|
|
37
|
+
*
|
|
38
|
+
* // Init the state
|
|
39
|
+
* observer.start(player.position, player.duration);
|
|
40
|
+
*
|
|
41
|
+
* // Update on a regular basis
|
|
42
|
+
* player.on('timeupdate', () => observer.update(player.position));
|
|
43
|
+
*
|
|
44
|
+
* // Notify any position change outside of the regular update
|
|
45
|
+
* player.on('seek', () => observer.seek(player.position));
|
|
46
|
+
*
|
|
47
|
+
* // Gets informed from any irregularity
|
|
48
|
+
* observer.on('irregularity', () => console.log('irregular jump in time');
|
|
49
|
+
*
|
|
50
|
+
* @param {number} interval - The typical interval expected between two updates. It is given in seconds.
|
|
51
|
+
* @returns {timeObserver}
|
|
52
|
+
*/
|
|
53
|
+
|
|
54
|
+
function timeObserverFactory() {
|
|
55
|
+
var interval = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1;
|
|
56
|
+
// Current time position
|
|
57
|
+
var position = 0; // Total duration expected
|
|
58
|
+
|
|
59
|
+
var duration = 0; // Last position forced
|
|
60
|
+
|
|
61
|
+
var _seek = 0;
|
|
62
|
+
/**
|
|
63
|
+
* Defines the API of a time observer.
|
|
64
|
+
*
|
|
65
|
+
* It observes the updates applied to a timeline, raising a flag when an irregularity occurs.
|
|
66
|
+
*
|
|
67
|
+
* @namespace timeObserver
|
|
68
|
+
*/
|
|
69
|
+
|
|
70
|
+
return eventifier({
|
|
71
|
+
/**
|
|
72
|
+
* Gets the current time position reported to the observer.
|
|
73
|
+
*
|
|
74
|
+
* @returns {number}
|
|
75
|
+
* @type {number}
|
|
76
|
+
* @member position
|
|
77
|
+
* @memberOf timeObserver
|
|
78
|
+
*/
|
|
79
|
+
get position() {
|
|
80
|
+
return position;
|
|
81
|
+
},
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Gets the total duration reported to the observer.
|
|
85
|
+
*
|
|
86
|
+
* @returns {number}
|
|
87
|
+
* @type {number}
|
|
88
|
+
* @member duration
|
|
89
|
+
* @memberOf timeObserver
|
|
90
|
+
*/
|
|
91
|
+
get duration() {
|
|
92
|
+
return duration;
|
|
93
|
+
},
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Initialises the time state.
|
|
97
|
+
*
|
|
98
|
+
* @param {number} initPosition - The initial time position
|
|
99
|
+
* @param {number} initDuration - The total duration expected
|
|
100
|
+
* @returns {timeObserver}
|
|
101
|
+
* @function init
|
|
102
|
+
* @memberOf timeObserver
|
|
103
|
+
*/
|
|
104
|
+
init: function init(initPosition, initDuration) {
|
|
105
|
+
position = _seek = initPosition;
|
|
106
|
+
duration = initDuration;
|
|
107
|
+
return this;
|
|
108
|
+
},
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Updates the time position. If the difference with the previous update is too high, an `irregularity` event
|
|
112
|
+
* will be emitted.
|
|
113
|
+
*
|
|
114
|
+
* @param {number} newPosition - The new time position
|
|
115
|
+
* @returns {timeObserver}
|
|
116
|
+
*
|
|
117
|
+
* @fires irregularity
|
|
118
|
+
*/
|
|
119
|
+
update: function update(newPosition) {
|
|
120
|
+
if (newPosition > _seek && newPosition - position > interval) {
|
|
121
|
+
/**
|
|
122
|
+
* Notifies an irregularity in the time update
|
|
123
|
+
* @event irregularity
|
|
124
|
+
* @param {number} position - last regular position
|
|
125
|
+
* @param {number} newPosition - new irregular position
|
|
126
|
+
*/
|
|
127
|
+
this.trigger('irregularity', position, newPosition);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
position = newPosition;
|
|
131
|
+
return this;
|
|
132
|
+
},
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Notifies the observer about a change in the position outside of the regular update.
|
|
136
|
+
*
|
|
137
|
+
* @param {number} seekPosition
|
|
138
|
+
* @returns {timeObserver}
|
|
139
|
+
*/
|
|
140
|
+
seek: function seek(seekPosition) {
|
|
141
|
+
position = _seek = seekPosition;
|
|
142
|
+
return this;
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
return timeObserverFactory;
|
|
148
|
+
|
|
149
|
+
});
|
package/dist/mediaplayer.js
CHANGED
|
@@ -146,7 +146,7 @@ define(['jquery', 'lodash', 'async', 'util/urlParser', 'core/eventifier', 'core/
|
|
|
146
146
|
+ escapeExpression((helper = helpers.__ || (depth0 && depth0.__),options={hash:{},data:data},helper ? helper.call(depth0, "Reload", options) : helperMissing.call(depth0, "__", "Reload", options)))
|
|
147
147
|
+ "\"></div>\n <div class=\"message\">"
|
|
148
148
|
+ escapeExpression((helper = helpers.__ || (depth0 && depth0.__),options={hash:{},data:data},helper ? helper.call(depth0, "You are encountering a prolonged connectivity loss.", options) : helperMissing.call(depth0, "__", "You are encountering a prolonged connectivity loss.", options)))
|
|
149
|
-
+ "
|
|
149
|
+
+ " "
|
|
150
150
|
+ escapeExpression((helper = helpers.__ || (depth0 && depth0.__),options={hash:{},data:data},helper ? helper.call(depth0, "Click to reload.", options) : helperMissing.call(depth0, "__", "Click to reload.", options)))
|
|
151
151
|
+ "</div>\n </a>\n </div>\n </div>\n <div class=\"controls\">\n <div class=\"bar\">\n <div class=\"control actions playback\">\n <a class=\"action play\" data-control=\"play\" title=\""
|
|
152
152
|
+ escapeExpression((helper = helpers.__ || (depth0 && depth0.__),options={hash:{},data:data},helper ? helper.call(depth0, "Play", options) : helperMissing.call(depth0, "__", "Play", options)))
|
|
@@ -236,7 +236,6 @@ define(['jquery', 'lodash', 'async', 'util/urlParser', 'core/eventifier', 'core/
|
|
|
236
236
|
startMuted: false,
|
|
237
237
|
maxPlays: 0,
|
|
238
238
|
replayTimeout: 0,
|
|
239
|
-
stalledTimeout: 2000,
|
|
240
239
|
canPause: true,
|
|
241
240
|
canSeek: true,
|
|
242
241
|
loop: false,
|
|
@@ -359,8 +358,14 @@ define(['jquery', 'lodash', 'async', 'util/urlParser', 'core/eventifier', 'core/
|
|
|
359
358
|
/**
|
|
360
359
|
* Builds a media player instance
|
|
361
360
|
* @param {Object} config
|
|
362
|
-
* @param {String} config.type - The type of media to play
|
|
363
|
-
*
|
|
361
|
+
* @param {String} config.type - The type of media to play, say `audio`, `video`, or `youtube`. The default is `video`.
|
|
362
|
+
* It might also contain the MIME type of the media as a shorthand.
|
|
363
|
+
* @param {String|Array} [config.url] - The URL to the media. If several media are proposed as alternatives,
|
|
364
|
+
* please look at the `sources` option instead.
|
|
365
|
+
* @param {String} [config.mimeType] - The MIME type of the media. If omitted, the player will try to extract it
|
|
366
|
+
* from the `type` property, otherwise it will request the server to get the content-type.
|
|
367
|
+
* @param {Array} [config.sources] - A list of URL if several media can be proposed. Each entry may be either a
|
|
368
|
+
* string (single URL), or an object containing both the URL and the MIME type ({src: string, type: string}).
|
|
364
369
|
* @param {String|jQuery|HTMLElement} [config.renderTo] - An optional container in which renders the player
|
|
365
370
|
* @param {Boolean} [config.canSeek] - The player allows to reach an arbitrary position within the media using the duration bar
|
|
366
371
|
* @param {Boolean} [config.loop] - The media will be played continuously
|
|
@@ -370,15 +375,14 @@ define(['jquery', 'lodash', 'async', 'util/urlParser', 'core/eventifier', 'core/
|
|
|
370
375
|
* @param {Number} [config.autoStartAt] - The time position at which the player should start
|
|
371
376
|
* @param {Number} [config.maxPlays] - Sets a few number of plays (default: infinite)
|
|
372
377
|
* @param {Number} [config.replayTimeout] - disable the possibility to replay a media after this timeout, in seconds (default: 0)
|
|
373
|
-
* @param {Number} [config.stalledTimeout] - delay before considering stalled playback (default: 2000)
|
|
374
378
|
* @param {Number} [config.volume] - Sets the sound volume (default: 80)
|
|
375
379
|
* @param {Number} [config.width] - Sets the width of the player (default: depends on media type)
|
|
376
380
|
* @param {Number} [config.height] - Sets the height of the player (default: depends on media type)
|
|
377
381
|
* @param {Boolean} [config.preview] - Enables the media preview (load media metadata)
|
|
378
382
|
* @param {Boolean} [config.debug] - Enables the debug mode
|
|
383
|
+
* @param {number} [config.config.stalledDetectionDelay] - The delay before considering a media is stalled
|
|
379
384
|
* @event render - Event triggered when the player is rendering
|
|
380
385
|
* @event error - Event triggered when the player throws an unrecoverable error
|
|
381
|
-
* @event recovererror - Event triggered when the player throws a recoverable error
|
|
382
386
|
* @event ready - Event triggered when the player is fully ready
|
|
383
387
|
* @event play - Event triggered when the playback is starting
|
|
384
388
|
* @event update - Event triggered while the player is playing
|
|
@@ -411,6 +415,10 @@ define(['jquery', 'lodash', 'async', 'util/urlParser', 'core/eventifier', 'core/
|
|
|
411
415
|
|
|
412
416
|
_.defaults(this.config, defaults.options);
|
|
413
417
|
|
|
418
|
+
if (!this.config.mimeType && 'string' === typeof this.config.type && this.config.type.indexOf('/') > 0) {
|
|
419
|
+
this.config.mimeType = this.config.type;
|
|
420
|
+
}
|
|
421
|
+
|
|
414
422
|
this._setType(this.config.type || defaults.type);
|
|
415
423
|
|
|
416
424
|
this._reset();
|
|
@@ -538,26 +546,15 @@ define(['jquery', 'lodash', 'async', 'util/urlParser', 'core/eventifier', 'core/
|
|
|
538
546
|
* Triggers a reload event
|
|
539
547
|
* @event mediaplayer#reload
|
|
540
548
|
*/
|
|
541
|
-
this.trigger('reload');
|
|
549
|
+
this.trigger('reload');
|
|
542
550
|
|
|
543
551
|
if (this.player) {
|
|
544
|
-
this.player.
|
|
545
|
-
}
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
if (this.$component) {
|
|
549
|
-
this._unbindEvents();
|
|
550
|
-
|
|
551
|
-
this._destroySlider(this.$seekSlider);
|
|
552
|
-
|
|
553
|
-
this._destroySlider(this.$volumeSlider);
|
|
554
|
-
|
|
555
|
-
this.$component.remove();
|
|
556
|
-
this.$component = null;
|
|
557
|
-
} // rerender
|
|
552
|
+
this.player.recover();
|
|
553
|
+
}
|
|
558
554
|
|
|
555
|
+
this._setState('stalled', false);
|
|
559
556
|
|
|
560
|
-
this.
|
|
557
|
+
this.setInitialStates();
|
|
561
558
|
},
|
|
562
559
|
|
|
563
560
|
/**
|
|
@@ -1002,8 +999,12 @@ define(['jquery', 'lodash', 'async', 'util/urlParser', 'core/eventifier', 'core/
|
|
|
1002
999
|
source = _.clone(src);
|
|
1003
1000
|
}
|
|
1004
1001
|
|
|
1005
|
-
if (
|
|
1006
|
-
|
|
1002
|
+
if (!source.type) {
|
|
1003
|
+
if (this.is('youtube')) {
|
|
1004
|
+
source.type = defaults.type;
|
|
1005
|
+
} else if (this.config.mimeType) {
|
|
1006
|
+
source.type = this.config.mimeType;
|
|
1007
|
+
}
|
|
1007
1008
|
}
|
|
1008
1009
|
|
|
1009
1010
|
if (!source.type) {
|
|
@@ -1093,7 +1094,8 @@ define(['jquery', 'lodash', 'async', 'util/urlParser', 'core/eventifier', 'core/
|
|
|
1093
1094
|
type: this.getType(),
|
|
1094
1095
|
sources: this.getSources(),
|
|
1095
1096
|
preview: this.config.preview,
|
|
1096
|
-
debug: this.config.debug
|
|
1097
|
+
debug: this.config.debug,
|
|
1098
|
+
stalledDetectionDelay: this.config.stalledDetectionDelay
|
|
1097
1099
|
};
|
|
1098
1100
|
this.player = playerFactory(this.$player, playerConfig).on('resize', function (width, height) {
|
|
1099
1101
|
if (_this6.$component) {
|
|
@@ -1115,8 +1117,6 @@ define(['jquery', 'lodash', 'async', 'util/urlParser', 'core/eventifier', 'core/
|
|
|
1115
1117
|
return _this6._onEnd();
|
|
1116
1118
|
}).on('error', function () {
|
|
1117
1119
|
return _this6._onError();
|
|
1118
|
-
}).on('recovererror', function (fromLoading) {
|
|
1119
|
-
return _this6._onRecoverError(fromLoading);
|
|
1120
1120
|
});
|
|
1121
1121
|
}
|
|
1122
1122
|
|
|
@@ -1135,7 +1135,13 @@ define(['jquery', 'lodash', 'async', 'util/urlParser', 'core/eventifier', 'core/
|
|
|
1135
1135
|
|
|
1136
1136
|
this._setState('preview', this.config.preview);
|
|
1137
1137
|
|
|
1138
|
-
this._setState('loading',
|
|
1138
|
+
this._setState('loading', !error);
|
|
1139
|
+
|
|
1140
|
+
if (error) {
|
|
1141
|
+
this._setState('ready', true);
|
|
1142
|
+
|
|
1143
|
+
this.trigger('ready');
|
|
1144
|
+
}
|
|
1139
1145
|
},
|
|
1140
1146
|
|
|
1141
1147
|
/**
|
|
@@ -1478,7 +1484,7 @@ define(['jquery', 'lodash', 'async', 'util/urlParser', 'core/eventifier', 'core/
|
|
|
1478
1484
|
*/
|
|
1479
1485
|
_onReady: function _onReady() {
|
|
1480
1486
|
if (this.is('error')) {
|
|
1481
|
-
this.
|
|
1487
|
+
this._setState('error', false);
|
|
1482
1488
|
}
|
|
1483
1489
|
|
|
1484
1490
|
var duration = this.player.getDuration();
|
|
@@ -1507,11 +1513,6 @@ define(['jquery', 'lodash', 'async', 'util/urlParser', 'core/eventifier', 'core/
|
|
|
1507
1513
|
|
|
1508
1514
|
if (this.config.preview && this.$container && this.config.height && this.config.height !== 'auto') {
|
|
1509
1515
|
this._setMaxHeight();
|
|
1510
|
-
} // seek back to the previous position after recover from stalled
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
if (this.is('stalled')) {
|
|
1514
|
-
this.play(this.positionBeforeStalled);
|
|
1515
1516
|
}
|
|
1516
1517
|
},
|
|
1517
1518
|
|
|
@@ -1585,29 +1586,6 @@ define(['jquery', 'lodash', 'async', 'util/urlParser', 'core/eventifier', 'core/
|
|
|
1585
1586
|
this.trigger('error');
|
|
1586
1587
|
},
|
|
1587
1588
|
|
|
1588
|
-
/**
|
|
1589
|
-
* Event called when the media throws recoverable error
|
|
1590
|
-
* @param {Boolean} fromLoading - recover from an error while loading the media
|
|
1591
|
-
* @private
|
|
1592
|
-
*/
|
|
1593
|
-
_onRecoverError: function _onRecoverError() {
|
|
1594
|
-
var fromLoading = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
|
|
1595
|
-
|
|
1596
|
-
// recover from playing error
|
|
1597
|
-
if (fromLoading && this.is('playing')) {
|
|
1598
|
-
this.render();
|
|
1599
|
-
}
|
|
1600
|
-
|
|
1601
|
-
this._setState('error', false);
|
|
1602
|
-
/**
|
|
1603
|
-
* Triggers a recoverable media error event
|
|
1604
|
-
* @event mediaplayer#recovererror
|
|
1605
|
-
*/
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
this.trigger('recovererror');
|
|
1609
|
-
},
|
|
1610
|
-
|
|
1611
1589
|
/**
|
|
1612
1590
|
* Event called when the media is played
|
|
1613
1591
|
* @private
|
|
@@ -1649,11 +1627,13 @@ define(['jquery', 'lodash', 'async', 'util/urlParser', 'core/eventifier', 'core/
|
|
|
1649
1627
|
|
|
1650
1628
|
this._playingState(false, true);
|
|
1651
1629
|
|
|
1652
|
-
this._updatePosition(0); // disable
|
|
1630
|
+
this._updatePosition(0); // disable when the play limit is reached
|
|
1653
1631
|
|
|
1654
1632
|
|
|
1655
1633
|
if (this._playLimitReached()) {
|
|
1656
|
-
this.
|
|
1634
|
+
if (!this.is('disabled')) {
|
|
1635
|
+
this.disable();
|
|
1636
|
+
}
|
|
1657
1637
|
/**
|
|
1658
1638
|
* Triggers a play limit reached event
|
|
1659
1639
|
* @event mediaplayer#limitreached
|
|
@@ -1694,20 +1674,9 @@ define(['jquery', 'lodash', 'async', 'util/urlParser', 'core/eventifier', 'core/
|
|
|
1694
1674
|
* @private
|
|
1695
1675
|
*/
|
|
1696
1676
|
_onStalled: function _onStalled() {
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
this.stalledTimeUpdateCount = 0;
|
|
1700
|
-
this.stalledTimer = window.setTimeout(function () {
|
|
1701
|
-
var position = _this9.getPosition();
|
|
1702
|
-
|
|
1703
|
-
if (position) {
|
|
1704
|
-
_this9.positionBeforeStalled = position;
|
|
1705
|
-
}
|
|
1677
|
+
this._setState('stalled', true);
|
|
1706
1678
|
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
_this9._setState('ready', false);
|
|
1710
|
-
}, this.config.stalledTimeout);
|
|
1679
|
+
this._setState('ready', false);
|
|
1711
1680
|
},
|
|
1712
1681
|
|
|
1713
1682
|
/**
|
|
@@ -1715,15 +1684,6 @@ define(['jquery', 'lodash', 'async', 'util/urlParser', 'core/eventifier', 'core/
|
|
|
1715
1684
|
* @private
|
|
1716
1685
|
*/
|
|
1717
1686
|
_onTimeUpdate: function _onTimeUpdate() {
|
|
1718
|
-
if (this.stalledTimer) {
|
|
1719
|
-
if (this.stalledTimeUpdateCount === 5) {
|
|
1720
|
-
window.clearTimeout(this.stalledTimer);
|
|
1721
|
-
this.stalledTimer = null;
|
|
1722
|
-
} else {
|
|
1723
|
-
this.stalledTimeUpdateCount++;
|
|
1724
|
-
}
|
|
1725
|
-
}
|
|
1726
|
-
|
|
1727
1687
|
this._updatePosition(this.player.getPosition());
|
|
1728
1688
|
/**
|
|
1729
1689
|
* Triggers a media time update event
|
|
@@ -1744,23 +1704,11 @@ define(['jquery', 'lodash', 'async', 'util/urlParser', 'core/eventifier', 'core/
|
|
|
1744
1704
|
this.timerId = requestAnimationFrame(this._replayTimeout.bind(this));
|
|
1745
1705
|
|
|
1746
1706
|
if (elapsedSeconds >= parseInt(this.config.replayTimeout, 10)) {
|
|
1747
|
-
this._disableGUI();
|
|
1748
|
-
|
|
1749
1707
|
this.disable();
|
|
1750
1708
|
cancelAnimationFrame(this.timerId);
|
|
1751
1709
|
}
|
|
1752
1710
|
},
|
|
1753
1711
|
|
|
1754
|
-
/**
|
|
1755
|
-
* Disable the player GUI
|
|
1756
|
-
* @private
|
|
1757
|
-
*/
|
|
1758
|
-
_disableGUI: function _disableGUI() {
|
|
1759
|
-
this._setState('ready', false);
|
|
1760
|
-
|
|
1761
|
-
this._setState('canplay', false);
|
|
1762
|
-
},
|
|
1763
|
-
|
|
1764
1712
|
/**
|
|
1765
1713
|
* Checks if the play limit has been reached
|
|
1766
1714
|
* @returns {Boolean}
|
|
@@ -1875,15 +1823,14 @@ define(['jquery', 'lodash', 'async', 'util/urlParser', 'core/eventifier', 'core/
|
|
|
1875
1823
|
* @private
|
|
1876
1824
|
*/
|
|
1877
1825
|
execute: function execute(command) {
|
|
1878
|
-
|
|
1879
|
-
|
|
1826
|
+
if (this.player && 'function' === typeof this.player[command]) {
|
|
1827
|
+
var _this$player;
|
|
1880
1828
|
|
|
1881
|
-
if (_.isFunction(method)) {
|
|
1882
1829
|
for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
|
|
1883
1830
|
args[_key2 - 1] = arguments[_key2];
|
|
1884
1831
|
}
|
|
1885
1832
|
|
|
1886
|
-
return
|
|
1833
|
+
return (_this$player = this.player)[command].apply(_this$player, args);
|
|
1887
1834
|
}
|
|
1888
1835
|
}
|
|
1889
1836
|
};
|