Skip to content

Commit 178474f

Browse files
authored
Merge pull request #31 from thuoe/feature/custom-events
feature/custom-events
2 parents d25c053 + 796e235 commit 178474f

File tree

4 files changed

+228
-15
lines changed

4 files changed

+228
-15
lines changed

README.md

+26-1
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ Or you can dynamically change the CSS properties at runtime..
158158
```js
159159
window.addEventListener('WebComponentsReady', () => {
160160
// when the video player element has finished initializing..
161-
const player = window.querySelector('mp4-video-player');
161+
const player = document.querySelector('mp4-video-player');
162162
player.updateStyles({
163163
'--video-min-width': '750px',
164164
'--video-min-height': '300px',
@@ -181,3 +181,28 @@ playback experience:
181181
| `` | Skip behind |
182182
| `` | Volume up |
183183
| `` | Volume down |
184+
185+
186+
## Custom Events
187+
188+
The player has a suite of events created using the CustomEvent API at your disposal to listen out for:
189+
190+
191+
| Event | Description | `event.detail` properties |
192+
|-------------------|-----------------------------------------------------|---------------------------|
193+
| `play` | When the video begins to play | `currentTime` |
194+
| `pause` | When the video has been paused | `currentTime` |
195+
| `ended` | When the video has ended | `currentTime` |
196+
| `exitFullscreen` | When exiting fullscreen mode | `currentTime` |
197+
| `enterFullscreen` | When entering fullscreen mode | `currentTime` |
198+
| `timeUpdated` | When the current time has updated to a new position | `currentTime` |
199+
| `volumeChange` | When the volume has been changed | `volume` |
200+
201+
Code Example:
202+
203+
```js
204+
const videoPlayer = document.querySelector('mp4-video-player');
205+
videoPlayer.addEventListener('timeUpdated', (event) => {
206+
console.log('Time Updated!', event.detail.currentTime);
207+
});
208+
```

demo/index.html

+20
Original file line numberDiff line numberDiff line change
@@ -32,5 +32,25 @@ <h3>Basic mp4-video-player demo</h3>
3232
</template>
3333
</demo-snippet>
3434
</div>
35+
<script>
36+
window.addEventListener('WebComponentsReady', () => {
37+
const player = document.querySelector('mp4-video-player');
38+
player.addEventListener('exitFullscreen', (e) => {
39+
console.log('Exit Fullscreen!', e.detail.currentTime);
40+
});
41+
player.addEventListener('enterFullscreen', (e) => {
42+
console.log('Enter Fullscreen!', e.detail.currentTime);
43+
});
44+
player.addEventListener('timeUpdated', (e) => {
45+
console.log('Time Updated!', e.detail.currentTime);
46+
});
47+
player.addEventListener('volumeChange', (e) => {
48+
console.log('New Volume!', e.detail.volume);
49+
});
50+
player.addEventListener('loadedmetadata', (e) => {
51+
console.log('Loaded!', e.detail.duration);
52+
});
53+
});
54+
</script>
3555
</body>
3656
</html>

mp4-video-player.js

+111-14
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,11 @@ class MP4VideoPlayer extends PolymerElement {
2828
autoplay$="[[autoPlay]]"
2929
loop$="[[loop]]"
3030
poster$="[[poster]]"
31-
on-play="_onPlay"
31+
on-play="_firePlayEvent"
32+
on-pause="_firePauseEvent"
33+
on-ended="_fireEndedEvent"
3234
on-loadedmetadata="_metadetaLoaded"
33-
on-timeupdate="_handleTimeUpdate"
34-
on-ended="_handleEnd">
35+
on-timeupdate="_handleTimeUpdate">
3536
<source src$="{{videoFilePath}}" type="video/mp4">
3637
</video>
3738
<div class="video-controls">
@@ -439,6 +440,7 @@ class MP4VideoPlayer extends PolymerElement {
439440
*/
440441
_metadetaLoaded(event) {
441442
const { duration } = event.currentTarget;
443+
this._fireLoadedmetadata();
442444
this._setDuration(duration);
443445
this._formattedDuration = this._formatTime(duration);
444446
}
@@ -471,13 +473,109 @@ class MP4VideoPlayer extends PolymerElement {
471473
return `${mins}:${secs}`;
472474
}
473475

476+
_createEvent(eventName, detail) {
477+
return new CustomEvent(eventName, { bubbles: true, detail });
478+
}
479+
480+
/**
481+
* Fire the appropriate event based on event type
482+
*/
483+
fireEvent(type) {
484+
switch (type) {
485+
case 'loaded':
486+
this._fireLoadedmetadata();
487+
break;
488+
case 'play':
489+
this._firePlayEvent();
490+
break;
491+
case 'pause':
492+
this._firePauseEvent();
493+
break;
494+
case 'ended':
495+
this._fireEndedEvent();
496+
break;
497+
case 'enterFullscreen':
498+
this._fireEnterFullscreenEvent();
499+
break;
500+
case 'exitFullscreen':
501+
this._fireExitFullscreenEvent();
502+
break;
503+
case 'timeUpdated':
504+
this._fireTimeUpdatedEvent();
505+
break;
506+
case 'volumeChange':
507+
this._fireVolumeChangeEvent();
508+
break;
509+
default:
510+
break;
511+
}
512+
}
513+
514+
/**
515+
* When the video has paused
516+
*/
517+
_fireLoadedmetadata() {
518+
const { duration } = this._getShadowElementById('video_player');
519+
this.dispatchEvent(this._createEvent('loadedmetadata', { duration }));
520+
}
521+
474522
/**
475523
* When the video has started to play
476524
*/
477-
_onPlay() {
525+
_firePlayEvent() {
526+
const { currentTime } = this._getShadowElementById('video_player');
478527
if (this.autoPlay) {
479528
this._setPlaying(true); // change the state of the track controls when initially playing..
480529
}
530+
this.dispatchEvent(this._createEvent('play', { currentTime }));
531+
}
532+
533+
/**
534+
* When the video has paused
535+
*/
536+
_firePauseEvent() {
537+
const { currentTime } = this._getShadowElementById('video_player');
538+
this.dispatchEvent(this._createEvent('pause', { currentTime }));
539+
}
540+
541+
/**
542+
* When the video has ended
543+
*/
544+
_fireEndedEvent() {
545+
const { currentTime } = this._getShadowElementById('video_player');
546+
this.dispatchEvent(this._createEvent('ended', { currentTime }));
547+
}
548+
549+
/**
550+
* When the video has enter fullscreen
551+
*/
552+
_fireEnterFullscreenEvent() {
553+
const { currentTime } = this._getShadowElementById('video_player');
554+
this.dispatchEvent(this._createEvent('enterFullscreen', { currentTime }));
555+
}
556+
557+
/**
558+
* When the video has exited fullscreen
559+
*/
560+
_fireExitFullscreenEvent() {
561+
const { currentTime } = this._getShadowElementById('video_player');
562+
this.dispatchEvent(this._createEvent('exitFullscreen', { currentTime }));
563+
}
564+
565+
/**
566+
* When the video has exited fullscreen
567+
*/
568+
_fireTimeUpdatedEvent() {
569+
const { currentTime } = this._getShadowElementById('video_player');
570+
this.dispatchEvent(this._createEvent('timeUpdated', { currentTime }));
571+
}
572+
573+
/**
574+
* When the video has changed volume
575+
*/
576+
_fireVolumeChangeEvent() {
577+
const { volume } = this._getShadowElementById('video_player');
578+
this.dispatchEvent(this._createEvent('volumeChange', { volume }));
481579
}
482580

483581
/**
@@ -501,6 +599,7 @@ class MP4VideoPlayer extends PolymerElement {
501599
*/
502600
_updateCurrentTime(progress) {
503601
const video = this._getShadowElementById('video_player');
602+
this._fireTimeUpdatedEvent();
504603
video.currentTime = progress;
505604
}
506605

@@ -583,7 +682,13 @@ class MP4VideoPlayer extends PolymerElement {
583682
* @private
584683
*/
585684
_handleFullscreenChange() {
586-
this._setFullscreen(!!document.fullscreenElement);
685+
const isFullscreen = !!document.fullscreenElement;
686+
if (isFullscreen) {
687+
this._fireEnterFullscreenEvent();
688+
} else {
689+
this._fireExitFullscreenEvent();
690+
}
691+
this._setFullscreen(isFullscreen);
587692
}
588693

589694
/**
@@ -610,15 +715,6 @@ class MP4VideoPlayer extends PolymerElement {
610715
this.volume = 0;
611716
}
612717

613-
/**
614-
* Dispatch a custom event when the video has
615-
* ended
616-
* @private
617-
*/
618-
_handleEnd() {
619-
this.dispatchEvent(new CustomEvent('videoEnded', { detail: { ended: true } }));
620-
}
621-
622718
/**
623719
* Toggle play the player
624720
* @private
@@ -690,6 +786,7 @@ class MP4VideoPlayer extends PolymerElement {
690786
this.prevVolume = oldVolume;
691787
this._setTrackPosition(newVolume, maxVolume, 'volume_');
692788
this._getShadowElementById('video_player').volume = newVolume;
789+
this._fireVolumeChangeEvent();
693790
}
694791

695792
/**

test/mp4-video-player_test.html

+71
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,77 @@
117117
});
118118
});
119119

120+
suite('player event listeners', () => {
121+
/* Timeout
122+
test('fires loadedmetadata event', (done) => {
123+
player.addEventListener('loadedmetadata', (event) => {
124+
expect(event.detail.duration).not.to.be.undefined;
125+
done();
126+
});
127+
player.fireEvent('loadedmetadata');
128+
}); */
129+
130+
test('fires play event', (done) => {
131+
player.addEventListener('play', (event) => {
132+
expect(event.detail.currentTime).not.to.be.undefined;
133+
done();
134+
});
135+
player.fireEvent('play');
136+
});
137+
138+
test('fires pause event', (done) => {
139+
player.addEventListener('pause', (event) => {
140+
expect(event.detail.currentTime).not.to.be.undefined;
141+
done();
142+
});
143+
player.fireEvent('pause');
144+
});
145+
146+
test('fires ended event', (done) => {
147+
player.addEventListener('ended', (event) => {
148+
expect(event.detail.currentTime).not.to.be.undefined;
149+
done();
150+
});
151+
player.fireEvent('ended');
152+
});
153+
154+
test('fires enterFullscreen event', (done) => {
155+
player.addEventListener('enterFullscreen', (event) => {
156+
expect(event.detail.currentTime).not.to.be.undefined;
157+
done();
158+
});
159+
player.fireEvent('enterFullscreen');
160+
});
161+
162+
test('fires exitFullscreen event', (done) => {
163+
player.addEventListener('exitFullscreen', (event) => {
164+
expect(event.detail.currentTime).not.to.be.undefined;
165+
done();
166+
});
167+
player.fireEvent('exitFullscreen');
168+
});
169+
170+
test('fires timeUpdated event', (done) => {
171+
player.addEventListener('timeUpdated', (event) => {
172+
expect(event.detail.currentTime).not.to.be.undefined;
173+
done();
174+
});
175+
player.fireEvent('timeUpdated');
176+
});
177+
178+
test('fires volumeChange event', (done) => {
179+
let alreadyDone = false;
180+
player.addEventListener('volumeChange', (event) => {
181+
expect(event.detail.volume).not.to.be.undefined;
182+
if (!alreadyDone) { // observer '_volumeChanged'
183+
alreadyDone = true;
184+
done();
185+
}
186+
});
187+
player.fireEvent('volumeChange');
188+
});
189+
});
190+
120191
suite('toggling functionality', () => {
121192
test('toggle play', () => {
122193
player.play = () => Promise.resolve();

0 commit comments

Comments
 (0)