@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,184 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This program is free software; you can redistribute it and/or
|
|
3
|
+
* modify it under the terms of the GNU General Public License
|
|
4
|
+
* as published by the Free Software Foundation; under version 2
|
|
5
|
+
* of the License (non-upgradable).
|
|
6
|
+
*
|
|
7
|
+
* This program is distributed in the hope that it will be useful,
|
|
8
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
9
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
10
|
+
* GNU General Public License for more details.
|
|
11
|
+
*
|
|
12
|
+
* You should have received a copy of the GNU General Public License
|
|
13
|
+
* along with this program; if not, write to the Free Software
|
|
14
|
+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
15
|
+
*
|
|
16
|
+
* Copyright (c) 2021 (original work) Open Assessment Technologies SA ;
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Creates a reminder manager.
|
|
21
|
+
*
|
|
22
|
+
* A reminder manager allows to register callback functions that will be called after a particular amount of time.
|
|
23
|
+
* The schedule can be created and cancelled at any time.
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* // Create a reminder manager
|
|
27
|
+
* const manager = reminderManagerFactory();
|
|
28
|
+
*
|
|
29
|
+
* // Add a reminder that will be called after 2s (delay is given in milliseconds)
|
|
30
|
+
* manager.remind(() => console.log('Hello!'), 2000);
|
|
31
|
+
*
|
|
32
|
+
* // Start the schedule
|
|
33
|
+
* manager.start();
|
|
34
|
+
*
|
|
35
|
+
* // We can know how many time elapsed since the last schedule
|
|
36
|
+
* const elapsed = manager.elapsed;
|
|
37
|
+
*
|
|
38
|
+
* // The schedule can be cancelled
|
|
39
|
+
* if (needToCancel) {
|
|
40
|
+
* manager.stop();
|
|
41
|
+
* }
|
|
42
|
+
*
|
|
43
|
+
* // The schedule should be cancelled
|
|
44
|
+
* console.log('schedule running:', manager.running)
|
|
45
|
+
*
|
|
46
|
+
* @returns {reminderManager}
|
|
47
|
+
*/
|
|
48
|
+
export default function reminderManagerFactory() {
|
|
49
|
+
// Keep track of the running state
|
|
50
|
+
let running = false;
|
|
51
|
+
|
|
52
|
+
// Timestamp of the last start
|
|
53
|
+
let last = 0;
|
|
54
|
+
|
|
55
|
+
// A list of reminders to callback
|
|
56
|
+
const reminders = new Map();
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Cancels a schedule for a particular reminder.
|
|
60
|
+
* @param {object} state - A sate object containing the timeout handler for the reminder.
|
|
61
|
+
* @private
|
|
62
|
+
*/
|
|
63
|
+
const stopReminder = state => {
|
|
64
|
+
if (state && state.timeout) {
|
|
65
|
+
clearTimeout(state.timeout);
|
|
66
|
+
state.timeout = null;
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Cancel the schedule for all reminders.
|
|
72
|
+
* @private
|
|
73
|
+
*/
|
|
74
|
+
const stopAllReminders = () => reminders.forEach(stopReminder);
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Schedule all reminders.
|
|
78
|
+
* @private
|
|
79
|
+
*/
|
|
80
|
+
const startAllReminders = () => {
|
|
81
|
+
reminders.forEach((state, reminder) => {
|
|
82
|
+
stopReminder(state);
|
|
83
|
+
state.timeout = setTimeout(reminder, state.delay);
|
|
84
|
+
});
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Defines the API of a reminder manager.
|
|
89
|
+
*
|
|
90
|
+
* A reminder manager allows to register callback functions that will be called after a particular amount of time.
|
|
91
|
+
* The schedule can be created and cancelled at any time.
|
|
92
|
+
*
|
|
93
|
+
* @namespace reminderManager
|
|
94
|
+
*/
|
|
95
|
+
return {
|
|
96
|
+
/**
|
|
97
|
+
* Tells whether or not the schedule is running.
|
|
98
|
+
* @type {boolean}
|
|
99
|
+
* @member running
|
|
100
|
+
* @memberOf reminderManager
|
|
101
|
+
*/
|
|
102
|
+
get running() {
|
|
103
|
+
return running;
|
|
104
|
+
},
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Gives the amount of time elapsed since the start of the schedule. It is given in milliseconds.
|
|
108
|
+
* If the schedule is not running, it will always be 0.
|
|
109
|
+
* @type {number}
|
|
110
|
+
* @member running
|
|
111
|
+
* @memberOf reminderManager
|
|
112
|
+
*/
|
|
113
|
+
get elapsed() {
|
|
114
|
+
if (!running) {
|
|
115
|
+
return 0;
|
|
116
|
+
}
|
|
117
|
+
return performance.now() - last;
|
|
118
|
+
},
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Schedules all reminders from now on.
|
|
122
|
+
*
|
|
123
|
+
* @returns {reminderManager}
|
|
124
|
+
* @function start
|
|
125
|
+
* @memberOf reminderManager
|
|
126
|
+
*/
|
|
127
|
+
start() {
|
|
128
|
+
running = true;
|
|
129
|
+
last = performance.now();
|
|
130
|
+
startAllReminders();
|
|
131
|
+
return this;
|
|
132
|
+
},
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Cancels all scheduled reminders.
|
|
136
|
+
*
|
|
137
|
+
* @returns {reminderManager}
|
|
138
|
+
* @function stop
|
|
139
|
+
* @memberOf reminderManager
|
|
140
|
+
*/
|
|
141
|
+
stop() {
|
|
142
|
+
running = false;
|
|
143
|
+
stopAllReminders();
|
|
144
|
+
return this;
|
|
145
|
+
},
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Adds a callback to be scheduled.
|
|
149
|
+
* It won't be scheduled until the schedule is restarted.
|
|
150
|
+
*
|
|
151
|
+
* @param {Function} cb - A function to call after the delay elapsed.
|
|
152
|
+
* @param {number} delay - The delay after what call back the reminder. It is given in milliseconds.
|
|
153
|
+
* @returns {reminderManager}
|
|
154
|
+
* @function remind
|
|
155
|
+
* @memberOf reminderManager
|
|
156
|
+
*/
|
|
157
|
+
remind(cb, delay) {
|
|
158
|
+
if ('function' === typeof cb && delay) {
|
|
159
|
+
stopReminder(reminders.get(cb));
|
|
160
|
+
reminders.set(cb, { delay });
|
|
161
|
+
}
|
|
162
|
+
return this;
|
|
163
|
+
},
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Removes a scheduled callback. If a schedule was running, it will be cancelled first.
|
|
167
|
+
*
|
|
168
|
+
* @param {Function} [cb] - The callback function to remove. If omitted, all reminders will be removed.
|
|
169
|
+
* @returns {reminderManager}
|
|
170
|
+
* @function forget
|
|
171
|
+
* @memberOf reminderManager
|
|
172
|
+
*/
|
|
173
|
+
forget(cb) {
|
|
174
|
+
if ('undefined' !== typeof cb) {
|
|
175
|
+
stopReminder(reminders.get(cb));
|
|
176
|
+
reminders.delete(cb);
|
|
177
|
+
} else {
|
|
178
|
+
stopAllReminders();
|
|
179
|
+
reminders.clear();
|
|
180
|
+
}
|
|
181
|
+
return this;
|
|
182
|
+
}
|
|
183
|
+
};
|
|
184
|
+
}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This program is free software; you can redistribute it and/or
|
|
3
|
+
* modify it under the terms of the GNU General Public License
|
|
4
|
+
* as published by the Free Software Foundation; under version 2
|
|
5
|
+
* of the License (non-upgradable).
|
|
6
|
+
*
|
|
7
|
+
* This program is distributed in the hope that it will be useful,
|
|
8
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
9
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
10
|
+
* GNU General Public License for more details.
|
|
11
|
+
*
|
|
12
|
+
* You should have received a copy of the GNU General Public License
|
|
13
|
+
* along with this program; if not, write to the Free Software
|
|
14
|
+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
15
|
+
*
|
|
16
|
+
* Copyright (c) 2021 (original work) Open Assessment Technologies SA ;
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import eventifier from 'core/eventifier';
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Creates a time observer.
|
|
23
|
+
*
|
|
24
|
+
* It observes the updates applied to a timeline, raising a flag when an irregularity occurs.
|
|
25
|
+
*
|
|
26
|
+
* It works as follow:
|
|
27
|
+
* - an initial state is defined (example: current: 0, duration: 100)
|
|
28
|
+
* - each time a position is forced (say the position is changed outside of the regular time update), the observer needs
|
|
29
|
+
* to be notified.
|
|
30
|
+
* - each time the position is updated (say regular time update), the observer needs to be called.
|
|
31
|
+
* - if the difference between the last regular update and the last one is too high, an event is triggered
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* // Create a time observer with an expected interval of 2 seconds
|
|
35
|
+
* const observer = timeObserverFactory(2);
|
|
36
|
+
*
|
|
37
|
+
* // Init the state
|
|
38
|
+
* observer.start(player.position, player.duration);
|
|
39
|
+
*
|
|
40
|
+
* // Update on a regular basis
|
|
41
|
+
* player.on('timeupdate', () => observer.update(player.position));
|
|
42
|
+
*
|
|
43
|
+
* // Notify any position change outside of the regular update
|
|
44
|
+
* player.on('seek', () => observer.seek(player.position));
|
|
45
|
+
*
|
|
46
|
+
* // Gets informed from any irregularity
|
|
47
|
+
* observer.on('irregularity', () => console.log('irregular jump in time');
|
|
48
|
+
*
|
|
49
|
+
* @param {number} interval - The typical interval expected between two updates. It is given in seconds.
|
|
50
|
+
* @returns {timeObserver}
|
|
51
|
+
*/
|
|
52
|
+
export default function timeObserverFactory(interval = 1) {
|
|
53
|
+
// Current time position
|
|
54
|
+
let position = 0;
|
|
55
|
+
|
|
56
|
+
// Total duration expected
|
|
57
|
+
let duration = 0;
|
|
58
|
+
|
|
59
|
+
// Last position forced
|
|
60
|
+
let seek = 0;
|
|
61
|
+
|
|
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
|
+
return eventifier({
|
|
70
|
+
/**
|
|
71
|
+
* Gets the current time position reported to the observer.
|
|
72
|
+
*
|
|
73
|
+
* @returns {number}
|
|
74
|
+
* @type {number}
|
|
75
|
+
* @member position
|
|
76
|
+
* @memberOf timeObserver
|
|
77
|
+
*/
|
|
78
|
+
get position() {
|
|
79
|
+
return position;
|
|
80
|
+
},
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Gets the total duration reported to the observer.
|
|
84
|
+
*
|
|
85
|
+
* @returns {number}
|
|
86
|
+
* @type {number}
|
|
87
|
+
* @member duration
|
|
88
|
+
* @memberOf timeObserver
|
|
89
|
+
*/
|
|
90
|
+
get duration() {
|
|
91
|
+
return duration;
|
|
92
|
+
},
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Initialises the time state.
|
|
96
|
+
*
|
|
97
|
+
* @param {number} initPosition - The initial time position
|
|
98
|
+
* @param {number} initDuration - The total duration expected
|
|
99
|
+
* @returns {timeObserver}
|
|
100
|
+
* @function init
|
|
101
|
+
* @memberOf timeObserver
|
|
102
|
+
*/
|
|
103
|
+
init(initPosition, initDuration) {
|
|
104
|
+
position = seek = initPosition;
|
|
105
|
+
duration = initDuration;
|
|
106
|
+
return this;
|
|
107
|
+
},
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Updates the time position. If the difference with the previous update is too high, an `irregularity` event
|
|
111
|
+
* will be emitted.
|
|
112
|
+
*
|
|
113
|
+
* @param {number} newPosition - The new time position
|
|
114
|
+
* @returns {timeObserver}
|
|
115
|
+
*
|
|
116
|
+
* @fires irregularity
|
|
117
|
+
*/
|
|
118
|
+
update(newPosition) {
|
|
119
|
+
if (newPosition > seek && newPosition - position > interval) {
|
|
120
|
+
/**
|
|
121
|
+
* Notifies an irregularity in the time update
|
|
122
|
+
* @event irregularity
|
|
123
|
+
* @param {number} position - last regular position
|
|
124
|
+
* @param {number} newPosition - new irregular position
|
|
125
|
+
*/
|
|
126
|
+
this.trigger('irregularity', position, newPosition);
|
|
127
|
+
}
|
|
128
|
+
position = newPosition;
|
|
129
|
+
return this;
|
|
130
|
+
},
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Notifies the observer about a change in the position outside of the regular update.
|
|
134
|
+
*
|
|
135
|
+
* @param {number} seekPosition
|
|
136
|
+
* @returns {timeObserver}
|
|
137
|
+
*/
|
|
138
|
+
seek(seekPosition) {
|
|
139
|
+
position = seek = seekPosition;
|
|
140
|
+
return this;
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
}
|
package/src/mediaplayer.js
CHANGED
|
@@ -77,7 +77,6 @@ const defaults = {
|
|
|
77
77
|
startMuted: false,
|
|
78
78
|
maxPlays: 0,
|
|
79
79
|
replayTimeout: 0,
|
|
80
|
-
stalledTimeout: 2000,
|
|
81
80
|
canPause: true,
|
|
82
81
|
canSeek: true,
|
|
83
82
|
loop: false,
|
|
@@ -190,8 +189,14 @@ const isResponsiveSize = sizeProps => {
|
|
|
190
189
|
/**
|
|
191
190
|
* Builds a media player instance
|
|
192
191
|
* @param {Object} config
|
|
193
|
-
* @param {String} config.type - The type of media to play
|
|
194
|
-
*
|
|
192
|
+
* @param {String} config.type - The type of media to play, say `audio`, `video`, or `youtube`. The default is `video`.
|
|
193
|
+
* It might also contain the MIME type of the media as a shorthand.
|
|
194
|
+
* @param {String|Array} [config.url] - The URL to the media. If several media are proposed as alternatives,
|
|
195
|
+
* please look at the `sources` option instead.
|
|
196
|
+
* @param {String} [config.mimeType] - The MIME type of the media. If omitted, the player will try to extract it
|
|
197
|
+
* from the `type` property, otherwise it will request the server to get the content-type.
|
|
198
|
+
* @param {Array} [config.sources] - A list of URL if several media can be proposed. Each entry may be either a
|
|
199
|
+
* string (single URL), or an object containing both the URL and the MIME type ({src: string, type: string}).
|
|
195
200
|
* @param {String|jQuery|HTMLElement} [config.renderTo] - An optional container in which renders the player
|
|
196
201
|
* @param {Boolean} [config.canSeek] - The player allows to reach an arbitrary position within the media using the duration bar
|
|
197
202
|
* @param {Boolean} [config.loop] - The media will be played continuously
|
|
@@ -201,15 +206,14 @@ const isResponsiveSize = sizeProps => {
|
|
|
201
206
|
* @param {Number} [config.autoStartAt] - The time position at which the player should start
|
|
202
207
|
* @param {Number} [config.maxPlays] - Sets a few number of plays (default: infinite)
|
|
203
208
|
* @param {Number} [config.replayTimeout] - disable the possibility to replay a media after this timeout, in seconds (default: 0)
|
|
204
|
-
* @param {Number} [config.stalledTimeout] - delay before considering stalled playback (default: 2000)
|
|
205
209
|
* @param {Number} [config.volume] - Sets the sound volume (default: 80)
|
|
206
210
|
* @param {Number} [config.width] - Sets the width of the player (default: depends on media type)
|
|
207
211
|
* @param {Number} [config.height] - Sets the height of the player (default: depends on media type)
|
|
208
212
|
* @param {Boolean} [config.preview] - Enables the media preview (load media metadata)
|
|
209
213
|
* @param {Boolean} [config.debug] - Enables the debug mode
|
|
214
|
+
* @param {number} [config.config.stalledDetectionDelay] - The delay before considering a media is stalled
|
|
210
215
|
* @event render - Event triggered when the player is rendering
|
|
211
216
|
* @event error - Event triggered when the player throws an unrecoverable error
|
|
212
|
-
* @event recovererror - Event triggered when the player throws a recoverable error
|
|
213
217
|
* @event ready - Event triggered when the player is fully ready
|
|
214
218
|
* @event play - Event triggered when the playback is starting
|
|
215
219
|
* @event update - Event triggered while the player is playing
|
|
@@ -234,6 +238,9 @@ function mediaplayerFactory(config) {
|
|
|
234
238
|
// load the config set, discard null values in order to allow defaults to be set
|
|
235
239
|
this.config = _.omit(config || {}, value => typeof value === 'undefined' || value === null);
|
|
236
240
|
_.defaults(this.config, defaults.options);
|
|
241
|
+
if (!this.config.mimeType && 'string' === typeof this.config.type && this.config.type.indexOf('/') > 0) {
|
|
242
|
+
this.config.mimeType = this.config.type;
|
|
243
|
+
}
|
|
237
244
|
this._setType(this.config.type || defaults.type);
|
|
238
245
|
|
|
239
246
|
this._reset();
|
|
@@ -345,23 +352,11 @@ function mediaplayerFactory(config) {
|
|
|
345
352
|
*/
|
|
346
353
|
this.trigger('reload');
|
|
347
354
|
|
|
348
|
-
// destroy player
|
|
349
355
|
if (this.player) {
|
|
350
|
-
this.player.
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
// remove events and component
|
|
354
|
-
if (this.$component) {
|
|
355
|
-
this._unbindEvents();
|
|
356
|
-
this._destroySlider(this.$seekSlider);
|
|
357
|
-
this._destroySlider(this.$volumeSlider);
|
|
358
|
-
|
|
359
|
-
this.$component.remove();
|
|
360
|
-
this.$component = null;
|
|
356
|
+
this.player.recover();
|
|
361
357
|
}
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
this.render();
|
|
358
|
+
this._setState('stalled', false);
|
|
359
|
+
this.setInitialStates();
|
|
365
360
|
},
|
|
366
361
|
|
|
367
362
|
/**
|
|
@@ -788,8 +783,12 @@ function mediaplayerFactory(config) {
|
|
|
788
783
|
source = _.clone(src);
|
|
789
784
|
}
|
|
790
785
|
|
|
791
|
-
if (
|
|
792
|
-
|
|
786
|
+
if (!source.type) {
|
|
787
|
+
if (this.is('youtube')) {
|
|
788
|
+
source.type = defaults.type;
|
|
789
|
+
} else if (this.config.mimeType) {
|
|
790
|
+
source.type = this.config.mimeType;
|
|
791
|
+
}
|
|
793
792
|
}
|
|
794
793
|
|
|
795
794
|
if (!source.type) {
|
|
@@ -872,7 +871,8 @@ function mediaplayerFactory(config) {
|
|
|
872
871
|
type: this.getType(),
|
|
873
872
|
sources: this.getSources(),
|
|
874
873
|
preview: this.config.preview,
|
|
875
|
-
debug: this.config.debug
|
|
874
|
+
debug: this.config.debug,
|
|
875
|
+
stalledDetectionDelay: this.config.stalledDetectionDelay
|
|
876
876
|
};
|
|
877
877
|
this.player = playerFactory(this.$player, playerConfig)
|
|
878
878
|
.on('resize', (width, height) => {
|
|
@@ -887,8 +887,7 @@ function mediaplayerFactory(config) {
|
|
|
887
887
|
.on('stalled', () => this._onStalled())
|
|
888
888
|
.on('playing', () => this._onPlaying())
|
|
889
889
|
.on('end', () => this._onEnd())
|
|
890
|
-
.on('error', () => this._onError())
|
|
891
|
-
.on('recovererror', fromLoading => this._onRecoverError(fromLoading));
|
|
890
|
+
.on('error', () => this._onError());
|
|
892
891
|
}
|
|
893
892
|
|
|
894
893
|
if (this.player) {
|
|
@@ -903,7 +902,11 @@ function mediaplayerFactory(config) {
|
|
|
903
902
|
this._setState('error', error);
|
|
904
903
|
this._setState('nogui', !support.canControl());
|
|
905
904
|
this._setState('preview', this.config.preview);
|
|
906
|
-
this._setState('loading',
|
|
905
|
+
this._setState('loading', !error);
|
|
906
|
+
if (error) {
|
|
907
|
+
this._setState('ready', true);
|
|
908
|
+
this.trigger('ready');
|
|
909
|
+
}
|
|
907
910
|
},
|
|
908
911
|
|
|
909
912
|
/**
|
|
@@ -1236,7 +1239,7 @@ function mediaplayerFactory(config) {
|
|
|
1236
1239
|
*/
|
|
1237
1240
|
_onReady() {
|
|
1238
1241
|
if (this.is('error')) {
|
|
1239
|
-
this.
|
|
1242
|
+
this._setState('error', false);
|
|
1240
1243
|
}
|
|
1241
1244
|
|
|
1242
1245
|
const duration = this.player.getDuration();
|
|
@@ -1264,11 +1267,6 @@ function mediaplayerFactory(config) {
|
|
|
1264
1267
|
if (this.config.preview && this.$container && this.config.height && this.config.height !== 'auto') {
|
|
1265
1268
|
this._setMaxHeight();
|
|
1266
1269
|
}
|
|
1267
|
-
|
|
1268
|
-
// seek back to the previous position after recover from stalled
|
|
1269
|
-
if (this.is('stalled')) {
|
|
1270
|
-
this.play(this.positionBeforeStalled);
|
|
1271
|
-
}
|
|
1272
1270
|
},
|
|
1273
1271
|
|
|
1274
1272
|
/**
|
|
@@ -1332,26 +1330,6 @@ function mediaplayerFactory(config) {
|
|
|
1332
1330
|
this.trigger('error');
|
|
1333
1331
|
},
|
|
1334
1332
|
|
|
1335
|
-
/**
|
|
1336
|
-
* Event called when the media throws recoverable error
|
|
1337
|
-
* @param {Boolean} fromLoading - recover from an error while loading the media
|
|
1338
|
-
* @private
|
|
1339
|
-
*/
|
|
1340
|
-
_onRecoverError(fromLoading = false) {
|
|
1341
|
-
// recover from playing error
|
|
1342
|
-
if (fromLoading && this.is('playing')) {
|
|
1343
|
-
this.render();
|
|
1344
|
-
}
|
|
1345
|
-
|
|
1346
|
-
this._setState('error', false);
|
|
1347
|
-
|
|
1348
|
-
/**
|
|
1349
|
-
* Triggers a recoverable media error event
|
|
1350
|
-
* @event mediaplayer#recovererror
|
|
1351
|
-
*/
|
|
1352
|
-
this.trigger('recovererror');
|
|
1353
|
-
},
|
|
1354
|
-
|
|
1355
1333
|
/**
|
|
1356
1334
|
* Event called when the media is played
|
|
1357
1335
|
* @private
|
|
@@ -1390,10 +1368,11 @@ function mediaplayerFactory(config) {
|
|
|
1390
1368
|
this._playingState(false, true);
|
|
1391
1369
|
this._updatePosition(0);
|
|
1392
1370
|
|
|
1393
|
-
// disable
|
|
1371
|
+
// disable when the play limit is reached
|
|
1394
1372
|
if (this._playLimitReached()) {
|
|
1395
|
-
this.
|
|
1396
|
-
|
|
1373
|
+
if (!this.is('disabled')) {
|
|
1374
|
+
this.disable();
|
|
1375
|
+
}
|
|
1397
1376
|
/**
|
|
1398
1377
|
* Triggers a play limit reached event
|
|
1399
1378
|
* @event mediaplayer#limitreached
|
|
@@ -1428,15 +1407,8 @@ function mediaplayerFactory(config) {
|
|
|
1428
1407
|
* @private
|
|
1429
1408
|
*/
|
|
1430
1409
|
_onStalled() {
|
|
1431
|
-
this.
|
|
1432
|
-
this.
|
|
1433
|
-
const position = this.getPosition();
|
|
1434
|
-
if (position) {
|
|
1435
|
-
this.positionBeforeStalled = position;
|
|
1436
|
-
}
|
|
1437
|
-
this._setState('stalled', true);
|
|
1438
|
-
this._setState('ready', false);
|
|
1439
|
-
}, this.config.stalledTimeout);
|
|
1410
|
+
this._setState('stalled', true);
|
|
1411
|
+
this._setState('ready', false);
|
|
1440
1412
|
},
|
|
1441
1413
|
|
|
1442
1414
|
/**
|
|
@@ -1444,15 +1416,6 @@ function mediaplayerFactory(config) {
|
|
|
1444
1416
|
* @private
|
|
1445
1417
|
*/
|
|
1446
1418
|
_onTimeUpdate() {
|
|
1447
|
-
if (this.stalledTimer) {
|
|
1448
|
-
if (this.stalledTimeUpdateCount === 5) {
|
|
1449
|
-
window.clearTimeout(this.stalledTimer);
|
|
1450
|
-
this.stalledTimer = null;
|
|
1451
|
-
} else {
|
|
1452
|
-
this.stalledTimeUpdateCount++;
|
|
1453
|
-
}
|
|
1454
|
-
}
|
|
1455
|
-
|
|
1456
1419
|
this._updatePosition(this.player.getPosition());
|
|
1457
1420
|
|
|
1458
1421
|
/**
|
|
@@ -1473,21 +1436,11 @@ function mediaplayerFactory(config) {
|
|
|
1473
1436
|
this.timerId = requestAnimationFrame(this._replayTimeout.bind(this));
|
|
1474
1437
|
|
|
1475
1438
|
if (elapsedSeconds >= parseInt(this.config.replayTimeout, 10)) {
|
|
1476
|
-
this._disableGUI();
|
|
1477
1439
|
this.disable();
|
|
1478
1440
|
cancelAnimationFrame(this.timerId);
|
|
1479
1441
|
}
|
|
1480
1442
|
},
|
|
1481
1443
|
|
|
1482
|
-
/**
|
|
1483
|
-
* Disable the player GUI
|
|
1484
|
-
* @private
|
|
1485
|
-
*/
|
|
1486
|
-
_disableGUI() {
|
|
1487
|
-
this._setState('ready', false);
|
|
1488
|
-
this._setState('canplay', false);
|
|
1489
|
-
},
|
|
1490
|
-
|
|
1491
1444
|
/**
|
|
1492
1445
|
* Checks if the play limit has been reached
|
|
1493
1446
|
* @returns {Boolean}
|
|
@@ -1605,11 +1558,8 @@ function mediaplayerFactory(config) {
|
|
|
1605
1558
|
* @private
|
|
1606
1559
|
*/
|
|
1607
1560
|
execute(command, ...args) {
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
if (_.isFunction(method)) {
|
|
1612
|
-
return method.apply(ctx, args);
|
|
1561
|
+
if (this.player && 'function' === typeof this.player[command]) {
|
|
1562
|
+
return this.player[command](...args);
|
|
1613
1563
|
}
|
|
1614
1564
|
}
|
|
1615
1565
|
};
|