|
1 import videojs from 'video.js'; |
|
2 import VimeoPlayer from '@vimeo/player'; |
|
3 |
|
4 let cssInjected = false; |
|
5 |
|
6 // Since the iframe can't be touched using Vimeo's way of embedding, |
|
7 // let's add a new styling rule to have the same style as `vjs-tech` |
|
8 function injectCss() { |
|
9 if (cssInjected) { |
|
10 return; |
|
11 } |
|
12 cssInjected = true; |
|
13 const css = ` |
|
14 .vjs-vimeo iframe { |
|
15 position: absolute; |
|
16 top: 0; |
|
17 left: 0; |
|
18 width: 100%; |
|
19 height: 100%; |
|
20 } |
|
21 `; |
|
22 const head = document.head || document.getElementsByTagName('head')[0]; |
|
23 |
|
24 const style = document.createElement('style'); |
|
25 |
|
26 style.type = 'text/css'; |
|
27 |
|
28 if (style.styleSheet) { |
|
29 style.styleSheet.cssText = css; |
|
30 } else { |
|
31 style.appendChild(document.createTextNode(css)); |
|
32 } |
|
33 |
|
34 head.appendChild(style); |
|
35 } |
|
36 |
|
37 const Tech = videojs.getTech('Tech'); |
|
38 |
|
39 /** |
|
40 * Vimeo - Wrapper for Video Player API |
|
41 * |
|
42 * @param {Object=} options Object of option names and values |
|
43 * @param {Function=} ready Ready callback function |
|
44 * @extends Tech |
|
45 * @class Vimeo |
|
46 */ |
|
47 class Vimeo extends Tech { |
|
48 constructor(options, ready) { |
|
49 super(options, ready); |
|
50 injectCss(); |
|
51 this.setPoster(options.poster); |
|
52 this.initVimeoPlayer(); |
|
53 } |
|
54 |
|
55 initVimeoPlayer() { |
|
56 const options = this.options({}); |
|
57 const vimeoOptions = { |
|
58 url: this.options_.source.src, |
|
59 byline: false, |
|
60 portrait: false, |
|
61 title: false, |
|
62 controls: false, |
|
63 }; |
|
64 |
|
65 if (this.options_.autoplay) { |
|
66 vimeoOptions.autoplay = true; |
|
67 } |
|
68 if (typeof(this.options_.controls) != "undefined") { |
|
69 vimeoOptions.controls = this.options_.controls; |
|
70 } |
|
71 |
|
72 if (this.options_.height) { |
|
73 vimeoOptions.height = this.options_.height; |
|
74 } |
|
75 if (this.options_.width) { |
|
76 vimeoOptions.width = this.options_.width; |
|
77 } |
|
78 if (this.options_.maxheight) { |
|
79 vimeoOptions.maxheight = this.options_.maxheight; |
|
80 } |
|
81 if (this.options_.maxwidth) { |
|
82 vimeoOptions.maxwidth = this.options_.maxwidth; |
|
83 } |
|
84 if (this.options_.loop) { |
|
85 vimeoOptions.loop = this.options_.loop; |
|
86 } |
|
87 if (this.options_.color) { |
|
88 vimeoOptions.color = this.options_.color.replace(/^#/, ''); |
|
89 } |
|
90 vimeoOptions.controls = false; |
|
91 |
|
92 |
|
93 this._player = new VimeoPlayer(this.el(), vimeoOptions); |
|
94 this.initVimeoState(); |
|
95 |
|
96 ['play', 'pause', 'ended', 'timeupdate', 'progress', 'seeked'].forEach(e => { |
|
97 this._player.on(e, (progress) => { |
|
98 if (this._vimeoState.progress.duration !== progress.duration) { |
|
99 this.trigger('durationchange'); |
|
100 } |
|
101 this._vimeoState.progress = progress; |
|
102 this.trigger(e); |
|
103 }); |
|
104 }); |
|
105 |
|
106 this._player.on('pause', () => (this._vimeoState.playing = false)); |
|
107 this._player.on('play', () => { |
|
108 this._vimeoState.playing = true; |
|
109 this._vimeoState.ended = false; |
|
110 }); |
|
111 this._player.on('ended', () => { |
|
112 this._vimeoState.playing = false; |
|
113 this._vimeoState.ended = true; |
|
114 }); |
|
115 this._player.on('volumechange', (v) => (this._vimeoState.volume = v)); |
|
116 this._player.on('error', e => this.trigger('error', e)); |
|
117 |
|
118 this.triggerReady(); |
|
119 } |
|
120 |
|
121 initVimeoState() { |
|
122 const state = this._vimeoState = { |
|
123 ended: false, |
|
124 playing: false, |
|
125 volume: 0, |
|
126 progress: { |
|
127 seconds: 0, |
|
128 percent: 0, |
|
129 duration: 0 |
|
130 } |
|
131 }; |
|
132 |
|
133 this._player.getCurrentTime().then(time => (state.progress.seconds = time)); |
|
134 this._player.getDuration().then(time => (state.progress.duration = time)); |
|
135 this._player.getPaused().then(paused => (state.playing = !paused)); |
|
136 this._player.getVolume().then(volume => (state.volume = volume)); |
|
137 } |
|
138 |
|
139 createEl() { |
|
140 const div = videojs.dom.createEl('div', { |
|
141 id: this.options_.techId |
|
142 }); |
|
143 |
|
144 div.style.cssText = 'width:100%;height:100%;top:0;left:0;position:absolute'; |
|
145 div.className = 'vjs-vimeo'; |
|
146 |
|
147 return div; |
|
148 } |
|
149 |
|
150 controls() { |
|
151 return true; |
|
152 } |
|
153 |
|
154 supportsFullScreen() { |
|
155 return true; |
|
156 } |
|
157 |
|
158 src() { |
|
159 return this.options_.source; |
|
160 } |
|
161 |
|
162 currentSrc() { |
|
163 return this.options_.source.src; |
|
164 } |
|
165 |
|
166 currentTime() { |
|
167 return this._vimeoState.progress.seconds; |
|
168 } |
|
169 |
|
170 setCurrentTime(time) { |
|
171 this._player.setCurrentTime(time); |
|
172 } |
|
173 |
|
174 volume() { |
|
175 return this._vimeoState.volume; |
|
176 } |
|
177 |
|
178 setVolume(volume) { |
|
179 return this._player.setVolume(volume); |
|
180 } |
|
181 |
|
182 duration() { |
|
183 return this._vimeoState.progress.duration; |
|
184 } |
|
185 |
|
186 buffered() { |
|
187 const progress = this._vimeoState.progress; |
|
188 |
|
189 return videojs.createTimeRange(0, progress.percent * progress.duration); |
|
190 } |
|
191 |
|
192 paused() { |
|
193 return !this._vimeoState.playing; |
|
194 } |
|
195 |
|
196 pause() { |
|
197 this._player.pause(); |
|
198 } |
|
199 |
|
200 play() { |
|
201 this._player.play(); |
|
202 } |
|
203 |
|
204 muted() { |
|
205 return this._vimeoState.volume === 0; |
|
206 } |
|
207 |
|
208 setMuted(muted) { |
|
209 return this._player.setMuted(muted); |
|
210 } |
|
211 |
|
212 ended() { |
|
213 return this._vimeoState.ended; |
|
214 } |
|
215 |
|
216 playbackRate() { |
|
217 return 1; |
|
218 } |
|
219 |
|
220 } |
|
221 |
|
222 Vimeo.prototype.featuresTimeupdateEvents = true; |
|
223 |
|
224 Vimeo.isSupported = function () { |
|
225 return true; |
|
226 }; |
|
227 |
|
228 // Add Source Handler pattern functions to this tech |
|
229 Tech.withSourceHandlers(Vimeo); |
|
230 |
|
231 Vimeo.nativeSourceHandler = { |
|
232 }; |
|
233 |
|
234 /** |
|
235 * Check if Vimeo can play the given videotype |
|
236 * |
|
237 * @param {string} source The mimetype to check |
|
238 * @return {string} 'maybe', or '' (empty string) |
|
239 */ |
|
240 Vimeo.nativeSourceHandler.canPlayType = function (source) { |
|
241 if (source === 'video/vimeo') { |
|
242 return 'maybe'; |
|
243 } |
|
244 |
|
245 return ''; |
|
246 }; |
|
247 |
|
248 /* |
|
249 * Check Vimeo can handle the source natively |
|
250 * |
|
251 * @param {Object} source The source object |
|
252 * @return {String} 'maybe', or '' (empty string) |
|
253 * @note: Copied over from YouTube — not sure this is relevant |
|
254 */ |
|
255 Vimeo.nativeSourceHandler.canHandleSource = function (source) { |
|
256 if (source.type) { |
|
257 return Vimeo.nativeSourceHandler.canPlayType(source.type); |
|
258 } else if (source.src) { |
|
259 return Vimeo.nativeSourceHandler.canPlayType(source.src); |
|
260 } |
|
261 |
|
262 return ''; |
|
263 }; |
|
264 |
|
265 // @note: Copied over from YouTube — not sure this is relevant |
|
266 Vimeo.nativeSourceHandler.handleSource = function (source, tech) { |
|
267 tech.src(source.src); |
|
268 }; |
|
269 |
|
270 // @note: Copied over from YouTube — not sure this is relevant |
|
271 Vimeo.nativeSourceHandler.dispose = function () { }; |
|
272 |
|
273 Vimeo.registerSourceHandler(Vimeo.nativeSourceHandler); |
|
274 |
|
275 // Older versions of VJS5 doesn't have the registerTech function |
|
276 if (typeof videojs.registerTech !== 'undefined') { |
|
277 videojs.registerTech('Vimeo', Vimeo); |
|
278 } else { |
|
279 videojs.registerComponent('Vimeo', Vimeo); |
|
280 } |
|
281 |
|
282 // Include the version number. |
|
283 Vimeo.VERSION = '0.0.1'; |
|
284 |
|
285 export default Vimeo; |