@cloudnest/redxplyr 1.0.0
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/.editorconfig +10 -0
- package/.gitpod.yml +6 -0
- package/.node-version +1 -0
- package/.prettierrc +7 -0
- package/.stickler.yml +5 -0
- package/.stylelintrc.json +26 -0
- package/CHANGELOG.md +16 -0
- package/CONTRIBUTING.md +34 -0
- package/CONTROLS.md +49 -0
- package/Dockerfile +32 -0
- package/LICENSE.md +22 -0
- package/README.md +194 -0
- package/cspell.json +48 -0
- package/dist/redxplyr.css +1 -0
- package/dist/redxplyr.js +8801 -0
- package/dist/redxplyr.min.js +2 -0
- package/dist/redxplyr.min.js.map +1 -0
- package/dist/redxplyr.min.mjs +1 -0
- package/dist/redxplyr.min.mjs.map +1 -0
- package/dist/redxplyr.mjs +8793 -0
- package/dist/redxplyr.polyfilled.js +9294 -0
- package/dist/redxplyr.polyfilled.min.js +2 -0
- package/dist/redxplyr.polyfilled.min.js.map +1 -0
- package/dist/redxplyr.polyfilled.min.mjs +1 -0
- package/dist/redxplyr.polyfilled.min.mjs.map +1 -0
- package/dist/redxplyr.polyfilled.mjs +9286 -0
- package/dist/redxplyr.svg +1 -0
- package/eslint.config.mjs +39 -0
- package/gulpfile.js +8 -0
- package/package.json +114 -0
- package/pnpm-workspace.yaml +8 -0
- package/src/js/captions.js +411 -0
- package/src/js/config/defaults.js +459 -0
- package/src/js/config/states.js +10 -0
- package/src/js/config/types.js +34 -0
- package/src/js/console.js +28 -0
- package/src/js/controls.js +1870 -0
- package/src/js/fullscreen.js +305 -0
- package/src/js/html5.js +148 -0
- package/src/js/listeners.js +854 -0
- package/src/js/media.js +61 -0
- package/src/js/plugins/ads.js +647 -0
- package/src/js/plugins/preview-thumbnails.js +706 -0
- package/src/js/plugins/vimeo.js +443 -0
- package/src/js/plugins/youtube.js +451 -0
- package/src/js/plyr.d.ts +729 -0
- package/src/js/plyr.js +1291 -0
- package/src/js/plyr.polyfilled.js +13 -0
- package/src/js/source.js +155 -0
- package/src/js/storage.js +70 -0
- package/src/js/support.js +100 -0
- package/src/js/ui.js +297 -0
- package/src/js/utils/animation.js +33 -0
- package/src/js/utils/arrays.js +23 -0
- package/src/js/utils/browser.js +21 -0
- package/src/js/utils/elements.js +263 -0
- package/src/js/utils/events.js +116 -0
- package/src/js/utils/fetch.js +45 -0
- package/src/js/utils/i18n.js +47 -0
- package/src/js/utils/is.js +81 -0
- package/src/js/utils/load-image.js +19 -0
- package/src/js/utils/load-script.js +14 -0
- package/src/js/utils/load-sprite.js +77 -0
- package/src/js/utils/numbers.js +17 -0
- package/src/js/utils/objects.js +43 -0
- package/src/js/utils/promise.js +14 -0
- package/src/js/utils/strings.js +80 -0
- package/src/js/utils/style.js +148 -0
- package/src/js/utils/time.js +36 -0
- package/src/js/utils/urls.js +40 -0
- package/src/sass/base.scss +69 -0
- package/src/sass/components/badges.scss +12 -0
- package/src/sass/components/captions.scss +58 -0
- package/src/sass/components/control.scss +52 -0
- package/src/sass/components/controls.scss +65 -0
- package/src/sass/components/menus.scss +205 -0
- package/src/sass/components/poster.scss +27 -0
- package/src/sass/components/progress.scss +107 -0
- package/src/sass/components/sliders.scss +99 -0
- package/src/sass/components/times.scss +20 -0
- package/src/sass/components/tooltips.scss +91 -0
- package/src/sass/components/volume.scss +18 -0
- package/src/sass/lib/animation.scss +31 -0
- package/src/sass/lib/css-vars.scss +103 -0
- package/src/sass/lib/functions.scss +3 -0
- package/src/sass/lib/mixins.scss +82 -0
- package/src/sass/plugins/ads.scss +53 -0
- package/src/sass/plugins/preview-thumbnails/index.scss +121 -0
- package/src/sass/plugins/preview-thumbnails/settings.scss +17 -0
- package/src/sass/plyr.scss +46 -0
- package/src/sass/settings/badges.scss +7 -0
- package/src/sass/settings/breakpoints.scss +9 -0
- package/src/sass/settings/captions.scss +10 -0
- package/src/sass/settings/colors.scss +18 -0
- package/src/sass/settings/controls.scss +30 -0
- package/src/sass/settings/cosmetics.scss +5 -0
- package/src/sass/settings/helpers.scss +7 -0
- package/src/sass/settings/menus.scss +13 -0
- package/src/sass/settings/progress.scss +18 -0
- package/src/sass/settings/sliders.scss +39 -0
- package/src/sass/settings/tooltips.scss +11 -0
- package/src/sass/settings/type.scss +16 -0
- package/src/sass/states/fullscreen.scss +15 -0
- package/src/sass/types/audio.scss +61 -0
- package/src/sass/types/video.scss +170 -0
- package/src/sass/utils/animation.scss +7 -0
- package/src/sass/utils/hidden.scss +28 -0
- package/src/sprite/plyr-airplay.svg +8 -0
- package/src/sprite/plyr-captions-off.svg +7 -0
- package/src/sprite/plyr-captions-on.svg +7 -0
- package/src/sprite/plyr-download.svg +8 -0
- package/src/sprite/plyr-enter-fullscreen.svg +4 -0
- package/src/sprite/plyr-exit-fullscreen.svg +4 -0
- package/src/sprite/plyr-fast-forward.svg +3 -0
- package/src/sprite/plyr-logo-vimeo.svg +6 -0
- package/src/sprite/plyr-logo-youtube.svg +6 -0
- package/src/sprite/plyr-muted.svg +8 -0
- package/src/sprite/plyr-pause.svg +8 -0
- package/src/sprite/plyr-pip.svg +6 -0
- package/src/sprite/plyr-play.svg +5 -0
- package/src/sprite/plyr-restart.svg +5 -0
- package/src/sprite/plyr-rewind.svg +3 -0
- package/src/sprite/plyr-settings.svg +5 -0
- package/src/sprite/plyr-volume.svg +11 -0
- package/tasks/build.js +226 -0
- package/tasks/deploy.js +216 -0
- package/tasks/utils/publish.js +34 -0
|
@@ -0,0 +1,443 @@
|
|
|
1
|
+
// ==========================================================================
|
|
2
|
+
// Vimeo plugin
|
|
3
|
+
// ==========================================================================
|
|
4
|
+
|
|
5
|
+
import captions from '../captions';
|
|
6
|
+
import controls from '../controls';
|
|
7
|
+
import ui from '../ui';
|
|
8
|
+
import { createElement, replaceElement, toggleClass } from '../utils/elements';
|
|
9
|
+
import { triggerEvent } from '../utils/events';
|
|
10
|
+
import fetch from '../utils/fetch';
|
|
11
|
+
import is from '../utils/is';
|
|
12
|
+
import loadScript from '../utils/load-script';
|
|
13
|
+
import { format, stripHTML } from '../utils/strings';
|
|
14
|
+
import { roundAspectRatio, setAspectRatio } from '../utils/style';
|
|
15
|
+
import { buildUrlParams } from '../utils/urls';
|
|
16
|
+
|
|
17
|
+
// Parse Vimeo ID from URL
|
|
18
|
+
function parseId(url) {
|
|
19
|
+
if (is.empty(url)) {
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
if (is.number(Number(url))) {
|
|
24
|
+
return url;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// eslint-disable-next-line regexp/optimal-quantifier-concatenation
|
|
28
|
+
const regex = /^.*(vimeo.com\/|video\/)(\d+).*/;
|
|
29
|
+
const match = url.match(regex);
|
|
30
|
+
return match ? match[2] : url;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Try to extract a hash for private videos from the URL
|
|
34
|
+
function parseHash(url) {
|
|
35
|
+
/* This regex matches a hexadecimal hash if given in any of these forms:
|
|
36
|
+
* - [https://player.]vimeo.com/video/{id}/{hash}[?params]
|
|
37
|
+
* - [https://player.]vimeo.com/video/{id}?h={hash}[¶ms]
|
|
38
|
+
* - [https://player.]vimeo.com/video/{id}?[params]&h={hash}
|
|
39
|
+
* - video/{id}/{hash}
|
|
40
|
+
* If matched, the hash is available in capture group 4
|
|
41
|
+
*/
|
|
42
|
+
const regex = /^.*(vimeo.com\/|video\/)(\d+)(\?.*h=|\/)+([\d,a-f]+)/;
|
|
43
|
+
const found = url.match(regex);
|
|
44
|
+
|
|
45
|
+
return found && found.length === 5 ? found[4] : null;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Set playback state and trigger change (only on actual change)
|
|
49
|
+
function assurePlaybackState(play) {
|
|
50
|
+
if (play && !this.embed.hasPlayed) {
|
|
51
|
+
this.embed.hasPlayed = true;
|
|
52
|
+
}
|
|
53
|
+
if (this.media.paused === play) {
|
|
54
|
+
this.media.paused = !play;
|
|
55
|
+
triggerEvent.call(this, this.media, play ? 'play' : 'pause');
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const vimeo = {
|
|
60
|
+
setup() {
|
|
61
|
+
const player = this;
|
|
62
|
+
|
|
63
|
+
// Add embed class for responsive
|
|
64
|
+
toggleClass(player.elements.wrapper, player.config.classNames.embed, true);
|
|
65
|
+
|
|
66
|
+
// Set speed options from config
|
|
67
|
+
player.options.speed = player.config.speed.options;
|
|
68
|
+
|
|
69
|
+
// Set initial ratio
|
|
70
|
+
setAspectRatio.call(player);
|
|
71
|
+
|
|
72
|
+
// Load the SDK if not already
|
|
73
|
+
if (!is.object(window.Vimeo)) {
|
|
74
|
+
loadScript(player.config.urls.vimeo.sdk)
|
|
75
|
+
.then(() => {
|
|
76
|
+
vimeo.ready.call(player);
|
|
77
|
+
})
|
|
78
|
+
.catch((error) => {
|
|
79
|
+
player.debug.warn('Vimeo SDK (player.js) failed to load', error);
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
vimeo.ready.call(player);
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
|
|
87
|
+
// API Ready
|
|
88
|
+
ready() {
|
|
89
|
+
const player = this;
|
|
90
|
+
const config = player.config.vimeo;
|
|
91
|
+
const { premium, referrerPolicy, ...frameParams } = config;
|
|
92
|
+
// Get the source URL or ID
|
|
93
|
+
let source = player.media.getAttribute('src');
|
|
94
|
+
let hash = '';
|
|
95
|
+
// Get from <div> if needed
|
|
96
|
+
if (is.empty(source)) {
|
|
97
|
+
source = player.media.getAttribute(player.config.attributes.embed.id);
|
|
98
|
+
// hash can also be set as attribute on the <div>
|
|
99
|
+
hash = player.media.getAttribute(player.config.attributes.embed.hash);
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
hash = parseHash(source);
|
|
103
|
+
}
|
|
104
|
+
const hashParam = hash ? { h: hash } : {};
|
|
105
|
+
|
|
106
|
+
// If the owner has a pro or premium account then we can hide controls etc
|
|
107
|
+
if (premium) {
|
|
108
|
+
Object.assign(frameParams, {
|
|
109
|
+
controls: false,
|
|
110
|
+
sidedock: false,
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// Get Vimeo params for the iframe
|
|
115
|
+
const params = buildUrlParams({
|
|
116
|
+
loop: player.config.loop.active,
|
|
117
|
+
autoplay: player.autoplay,
|
|
118
|
+
muted: player.muted,
|
|
119
|
+
gesture: 'media',
|
|
120
|
+
playsinline: player.config.playsinline,
|
|
121
|
+
// hash has to be added to iframe-URL
|
|
122
|
+
...hashParam,
|
|
123
|
+
...frameParams,
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
const id = parseId(source);
|
|
127
|
+
// Build an iframe
|
|
128
|
+
const iframe = createElement('iframe');
|
|
129
|
+
const src = format(player.config.urls.vimeo.iframe, id, params);
|
|
130
|
+
iframe.setAttribute('src', src);
|
|
131
|
+
iframe.setAttribute('allowfullscreen', '');
|
|
132
|
+
iframe.setAttribute(
|
|
133
|
+
'allow',
|
|
134
|
+
['autoplay', 'fullscreen', 'picture-in-picture', 'encrypted-media', 'accelerometer', 'gyroscope'].join('; '),
|
|
135
|
+
);
|
|
136
|
+
|
|
137
|
+
// Set the referrer policy if required
|
|
138
|
+
if (!is.empty(referrerPolicy)) {
|
|
139
|
+
iframe.setAttribute('referrerPolicy', referrerPolicy);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// Inject the package
|
|
143
|
+
if (premium || !config.customControls) {
|
|
144
|
+
iframe.setAttribute('data-poster', player.poster);
|
|
145
|
+
player.media = replaceElement(iframe, player.media);
|
|
146
|
+
}
|
|
147
|
+
else {
|
|
148
|
+
const wrapper = createElement('div', {
|
|
149
|
+
'class': player.config.classNames.embedContainer,
|
|
150
|
+
'data-poster': player.poster,
|
|
151
|
+
});
|
|
152
|
+
wrapper.appendChild(iframe);
|
|
153
|
+
player.media = replaceElement(wrapper, player.media);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// Get poster image
|
|
157
|
+
if (!config.customControls) {
|
|
158
|
+
fetch(format(player.config.urls.vimeo.api, src)).then((response) => {
|
|
159
|
+
if (is.empty(response) || !response.thumbnail_url) {
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// Set and show poster
|
|
164
|
+
ui.setPoster.call(player, response.thumbnail_url).catch(() => {});
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// Setup instance
|
|
169
|
+
// https://github.com/vimeo/player.js
|
|
170
|
+
player.embed = new window.Vimeo.Player(iframe, {
|
|
171
|
+
autopause: player.config.autopause,
|
|
172
|
+
muted: player.muted,
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
player.media.paused = true;
|
|
176
|
+
player.media.currentTime = 0;
|
|
177
|
+
|
|
178
|
+
// Disable native text track rendering
|
|
179
|
+
if (player.supported.ui) {
|
|
180
|
+
player.embed.disableTextTrack();
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// Create a faux HTML5 API using the Vimeo API
|
|
184
|
+
player.media.play = () => {
|
|
185
|
+
assurePlaybackState.call(player, true);
|
|
186
|
+
return player.embed.play();
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
player.media.pause = () => {
|
|
190
|
+
assurePlaybackState.call(player, false);
|
|
191
|
+
return player.embed.pause();
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
player.media.stop = () => {
|
|
195
|
+
player.pause();
|
|
196
|
+
player.currentTime = 0;
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
// Seeking
|
|
200
|
+
let { currentTime } = player.media;
|
|
201
|
+
Object.defineProperty(player.media, 'currentTime', {
|
|
202
|
+
get() {
|
|
203
|
+
return currentTime;
|
|
204
|
+
},
|
|
205
|
+
set(time) {
|
|
206
|
+
// Vimeo will automatically play on seek if the video hasn't been played before
|
|
207
|
+
|
|
208
|
+
// Get current paused state and volume etc
|
|
209
|
+
const { embed, media, paused, volume } = player;
|
|
210
|
+
const restorePause = paused && !embed.hasPlayed;
|
|
211
|
+
|
|
212
|
+
// Set seeking state and trigger event
|
|
213
|
+
media.seeking = true;
|
|
214
|
+
triggerEvent.call(player, media, 'seeking');
|
|
215
|
+
|
|
216
|
+
// If paused, mute until seek is complete
|
|
217
|
+
Promise.resolve(restorePause && embed.setVolume(0))
|
|
218
|
+
// Seek
|
|
219
|
+
.then(() => embed.setCurrentTime(time))
|
|
220
|
+
// Restore paused
|
|
221
|
+
.then(() => restorePause && embed.pause())
|
|
222
|
+
// Restore volume
|
|
223
|
+
.then(() => restorePause && embed.setVolume(volume))
|
|
224
|
+
.catch(() => {
|
|
225
|
+
// Do nothing
|
|
226
|
+
});
|
|
227
|
+
},
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
// Playback speed
|
|
231
|
+
let speed = player.config.speed.selected;
|
|
232
|
+
Object.defineProperty(player.media, 'playbackRate', {
|
|
233
|
+
get() {
|
|
234
|
+
return speed;
|
|
235
|
+
},
|
|
236
|
+
set(input) {
|
|
237
|
+
player.embed
|
|
238
|
+
.setPlaybackRate(input)
|
|
239
|
+
.then(() => {
|
|
240
|
+
speed = input;
|
|
241
|
+
triggerEvent.call(player, player.media, 'ratechange');
|
|
242
|
+
})
|
|
243
|
+
.catch(() => {
|
|
244
|
+
// Cannot set Playback Rate, Video is probably not on Pro account
|
|
245
|
+
player.options.speed = [1];
|
|
246
|
+
});
|
|
247
|
+
},
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
// Volume
|
|
251
|
+
let { volume } = player.config;
|
|
252
|
+
Object.defineProperty(player.media, 'volume', {
|
|
253
|
+
get() {
|
|
254
|
+
return volume;
|
|
255
|
+
},
|
|
256
|
+
set(input) {
|
|
257
|
+
player.embed.setVolume(input).then(() => {
|
|
258
|
+
volume = input;
|
|
259
|
+
triggerEvent.call(player, player.media, 'volumechange');
|
|
260
|
+
});
|
|
261
|
+
},
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
// Muted
|
|
265
|
+
let { muted } = player.config;
|
|
266
|
+
Object.defineProperty(player.media, 'muted', {
|
|
267
|
+
get() {
|
|
268
|
+
return muted;
|
|
269
|
+
},
|
|
270
|
+
set(input) {
|
|
271
|
+
const toggle = is.boolean(input) ? input : false;
|
|
272
|
+
|
|
273
|
+
player.embed.setMuted(toggle ? true : player.config.muted).then(() => {
|
|
274
|
+
muted = toggle;
|
|
275
|
+
triggerEvent.call(player, player.media, 'volumechange');
|
|
276
|
+
});
|
|
277
|
+
},
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
// Loop
|
|
281
|
+
let { loop } = player.config;
|
|
282
|
+
Object.defineProperty(player.media, 'loop', {
|
|
283
|
+
get() {
|
|
284
|
+
return loop;
|
|
285
|
+
},
|
|
286
|
+
set(input) {
|
|
287
|
+
const toggle = is.boolean(input) ? input : player.config.loop.active;
|
|
288
|
+
|
|
289
|
+
player.embed.setLoop(toggle).then(() => {
|
|
290
|
+
loop = toggle;
|
|
291
|
+
});
|
|
292
|
+
},
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
// Source
|
|
296
|
+
let currentSrc;
|
|
297
|
+
player.embed
|
|
298
|
+
.getVideoUrl()
|
|
299
|
+
.then((value) => {
|
|
300
|
+
currentSrc = value;
|
|
301
|
+
controls.setDownloadUrl.call(player);
|
|
302
|
+
})
|
|
303
|
+
.catch((error) => {
|
|
304
|
+
this.debug.warn(error);
|
|
305
|
+
});
|
|
306
|
+
|
|
307
|
+
Object.defineProperty(player.media, 'currentSrc', {
|
|
308
|
+
get() {
|
|
309
|
+
return currentSrc;
|
|
310
|
+
},
|
|
311
|
+
});
|
|
312
|
+
|
|
313
|
+
// Ended
|
|
314
|
+
Object.defineProperty(player.media, 'ended', {
|
|
315
|
+
get() {
|
|
316
|
+
return player.currentTime === player.duration;
|
|
317
|
+
},
|
|
318
|
+
});
|
|
319
|
+
|
|
320
|
+
// Set aspect ratio based on video size
|
|
321
|
+
Promise.all([player.embed.getVideoWidth(), player.embed.getVideoHeight()]).then((dimensions) => {
|
|
322
|
+
const [width, height] = dimensions;
|
|
323
|
+
player.embed.ratio = roundAspectRatio(width, height);
|
|
324
|
+
setAspectRatio.call(this);
|
|
325
|
+
});
|
|
326
|
+
|
|
327
|
+
// Set autopause
|
|
328
|
+
player.embed.setAutopause(player.config.autopause).then((state) => {
|
|
329
|
+
player.config.autopause = state;
|
|
330
|
+
});
|
|
331
|
+
|
|
332
|
+
// Get title
|
|
333
|
+
player.embed.getVideoTitle().then((title) => {
|
|
334
|
+
player.config.title = title;
|
|
335
|
+
ui.setTitle.call(this);
|
|
336
|
+
});
|
|
337
|
+
|
|
338
|
+
// Get current time
|
|
339
|
+
player.embed.getCurrentTime().then((value) => {
|
|
340
|
+
currentTime = value;
|
|
341
|
+
triggerEvent.call(player, player.media, 'timeupdate');
|
|
342
|
+
});
|
|
343
|
+
|
|
344
|
+
// Get duration
|
|
345
|
+
player.embed.getDuration().then((value) => {
|
|
346
|
+
player.media.duration = value;
|
|
347
|
+
triggerEvent.call(player, player.media, 'durationchange');
|
|
348
|
+
});
|
|
349
|
+
|
|
350
|
+
// Get captions
|
|
351
|
+
player.embed.getTextTracks().then((tracks) => {
|
|
352
|
+
player.media.textTracks = tracks;
|
|
353
|
+
captions.setup.call(player);
|
|
354
|
+
});
|
|
355
|
+
|
|
356
|
+
player.embed.on('cuechange', ({ cues = [] }) => {
|
|
357
|
+
const strippedCues = cues.map(cue => stripHTML(cue.text));
|
|
358
|
+
captions.updateCues.call(player, strippedCues);
|
|
359
|
+
});
|
|
360
|
+
|
|
361
|
+
player.embed.on('loaded', () => {
|
|
362
|
+
// Assure state and events are updated on autoplay
|
|
363
|
+
player.embed.getPaused().then((paused) => {
|
|
364
|
+
assurePlaybackState.call(player, !paused);
|
|
365
|
+
if (!paused) {
|
|
366
|
+
triggerEvent.call(player, player.media, 'playing');
|
|
367
|
+
}
|
|
368
|
+
});
|
|
369
|
+
|
|
370
|
+
if (is.element(player.embed.element) && player.supported.ui) {
|
|
371
|
+
const frame = player.embed.element;
|
|
372
|
+
|
|
373
|
+
// Fix keyboard focus issues
|
|
374
|
+
// https://github.com/xgauravyaduvanshii/redxplyr/issues/317
|
|
375
|
+
frame.setAttribute('tabindex', -1);
|
|
376
|
+
}
|
|
377
|
+
});
|
|
378
|
+
|
|
379
|
+
player.embed.on('bufferstart', () => {
|
|
380
|
+
triggerEvent.call(player, player.media, 'waiting');
|
|
381
|
+
});
|
|
382
|
+
|
|
383
|
+
player.embed.on('bufferend', () => {
|
|
384
|
+
triggerEvent.call(player, player.media, 'playing');
|
|
385
|
+
});
|
|
386
|
+
|
|
387
|
+
player.embed.on('play', () => {
|
|
388
|
+
assurePlaybackState.call(player, true);
|
|
389
|
+
triggerEvent.call(player, player.media, 'playing');
|
|
390
|
+
});
|
|
391
|
+
|
|
392
|
+
player.embed.on('pause', () => {
|
|
393
|
+
assurePlaybackState.call(player, false);
|
|
394
|
+
});
|
|
395
|
+
|
|
396
|
+
player.embed.on('timeupdate', (data) => {
|
|
397
|
+
player.media.seeking = false;
|
|
398
|
+
currentTime = data.seconds;
|
|
399
|
+
triggerEvent.call(player, player.media, 'timeupdate');
|
|
400
|
+
});
|
|
401
|
+
|
|
402
|
+
player.embed.on('progress', (data) => {
|
|
403
|
+
player.media.buffered = data.percent;
|
|
404
|
+
triggerEvent.call(player, player.media, 'progress');
|
|
405
|
+
|
|
406
|
+
// Check all loaded
|
|
407
|
+
if (Number.parseInt(data.percent, 10) === 1) {
|
|
408
|
+
triggerEvent.call(player, player.media, 'canplaythrough');
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
// Get duration as if we do it before load, it gives an incorrect value
|
|
412
|
+
// https://github.com/xgauravyaduvanshii/redxplyr/issues/891
|
|
413
|
+
player.embed.getDuration().then((value) => {
|
|
414
|
+
if (value !== player.media.duration) {
|
|
415
|
+
player.media.duration = value;
|
|
416
|
+
triggerEvent.call(player, player.media, 'durationchange');
|
|
417
|
+
}
|
|
418
|
+
});
|
|
419
|
+
});
|
|
420
|
+
|
|
421
|
+
player.embed.on('seeked', () => {
|
|
422
|
+
player.media.seeking = false;
|
|
423
|
+
triggerEvent.call(player, player.media, 'seeked');
|
|
424
|
+
});
|
|
425
|
+
|
|
426
|
+
player.embed.on('ended', () => {
|
|
427
|
+
player.media.paused = true;
|
|
428
|
+
triggerEvent.call(player, player.media, 'ended');
|
|
429
|
+
});
|
|
430
|
+
|
|
431
|
+
player.embed.on('error', (detail) => {
|
|
432
|
+
player.media.error = detail;
|
|
433
|
+
triggerEvent.call(player, player.media, 'error');
|
|
434
|
+
});
|
|
435
|
+
|
|
436
|
+
// Rebuild UI
|
|
437
|
+
if (config.customControls) {
|
|
438
|
+
setTimeout(() => ui.build.call(player), 0);
|
|
439
|
+
}
|
|
440
|
+
},
|
|
441
|
+
};
|
|
442
|
+
|
|
443
|
+
export default vimeo;
|