Skip to content

Commit

Permalink
feat!: allow using any HTMLMediaElement
Browse files Browse the repository at this point in the history
BREAKING CHANGE: videoElement argument renamed to mediaElement

OLD: getMediaEventFilter({ videoElement });
NEW: getMediaEventFilter({ mediaElement });
  • Loading branch information
martinstark committed Apr 2, 2024
1 parent a3f6e2f commit 5b502e9
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 25 deletions.
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Media Event Filter

A dependecy free, tiny package for producing a sane default interpretation of playback events from a [HTMLVideoElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLVideoElement).
A dependecy free, tiny package for producing a sane default interpretation of playback events from a [HTMLMediaElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement).

## Why

Expand Down Expand Up @@ -37,7 +37,7 @@ const videoElement = document.createElement("video");
// Using a switch statement

const mediaEventFilter = getMediaEventFilter({
videoElement,
mediaElement: videoElement,
callback: (event: FilteredMediaEvent) => {
switch (event) {
case FilteredMediaEvent.LOADED:
Expand Down Expand Up @@ -76,7 +76,7 @@ const handlers = {
};

const mediaEventFilter = getMediaEventFilter({
videoElement,
mediaElement: videoElement,
callback: (event: FilteredMediaEvent) => handlers[event]?.(),
});
```
Expand Down Expand Up @@ -115,7 +115,7 @@ const PlayerComponent = ({ videoUrl }) => {
if (!videoUrl || !videoRef.current) return () => {};

const eventFilter = getMediaEventFilter({
videoElement: videoRef.current,
mediaElement: videoRef.current,
// add your state handlers here
callback: (event) => {
switch (event) {
Expand Down
6 changes: 3 additions & 3 deletions public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -70,17 +70,17 @@
MediaEvent,
} from "./main.mjs";

const videoElement = document.getElementById("videoEl");
const mediaElement = document.getElementById("videoEl");
let i = 1;

Object.values(MediaEvent).forEach((evt) =>
videoElement.addEventListener(evt, () => {
mediaElement.addEventListener(evt, () => {
console.log("%cNativeEv: %s", "color:#cf1313;font-weight:bold;", evt);
}),
);

getMediaEventFilter({
videoElement,
mediaElement,
callback: (evt) => {
console.log("%cFiltered: %s", "color:#267dff;font-weight:bold;", evt);

Expand Down
36 changes: 18 additions & 18 deletions src/media-event-filter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export enum FilteredMediaEvent {
type TFilteredMediaEventCallback = (event: FilteredMediaEvent) => void;

type TMediaEventFilterOptions = {
videoElement: HTMLVideoElement;
mediaElement: HTMLMediaElement;
callback: TFilteredMediaEventCallback;
allowResumeAfterEnded?: boolean;
};
Expand Down Expand Up @@ -77,10 +77,10 @@ const initialState = {
ended: false,
// true until the video is ready to play, only toggles once
loading: true,
// true when the videoElement behavior is interpreted as buffering
// true when the mediaElement behavior is interpreted as buffering
// should not toggle while seeking
buffering: false,
// true when the videoElement behavior is interpreted as seeking
// true when the mediaElement behavior is interpreted as seeking
// a seek should cancel buffering
seeking: false,
// initial play is different from subsequent plays, because paused is false
Expand All @@ -100,7 +100,7 @@ export type TMediaEventFilter = {
};

export const getMediaEventFilter = ({
videoElement,
mediaElement,
callback,
allowResumeAfterEnded = false,
}: TMediaEventFilterOptions): TMediaEventFilter => {
Expand All @@ -122,7 +122,7 @@ export const getMediaEventFilter = ({
const onCanPlayThrough = (): void => {
if (!state.loading) {
// Recover from Safari "mute" micro buffer triggered by "waiting"
if (state.buffering && videoElement.playbackRate > 0) {
if (state.buffering && mediaElement.playbackRate > 0) {
state = {
...state,
buffering: false,
Expand All @@ -135,7 +135,7 @@ export const getMediaEventFilter = ({
if (state.loading) {
// guard for when an engine sets playbackRate to 0 to continue buffering
// recover in "ratechange" event
if (videoElement.playbackRate === 0) {
if (mediaElement.playbackRate === 0) {
state = {
...state,
deferLoadedEvent: true,
Expand Down Expand Up @@ -183,7 +183,7 @@ export const getMediaEventFilter = ({

// guard for when an engine sets playbackRate to 0 to continue buffering
// recover in "ratechange" event
if (videoElement.playbackRate === 0) {
if (mediaElement.playbackRate === 0) {
state = {
...state,
deferSeekedEvent: true,
Expand All @@ -210,7 +210,7 @@ export const getMediaEventFilter = ({
if (state.seeking) return;

// some browsers send "waiting" before the "seeking" event
if (videoElement.seeking) {
if (mediaElement.seeking) {
onSeeking();
return;
}
Expand Down Expand Up @@ -247,7 +247,7 @@ export const getMediaEventFilter = ({

// guard for when an engine sets playbackRate to 0 to continue buffering
// recover in "ratechange" event
if (videoElement.playbackRate === 0) {
if (mediaElement.playbackRate === 0) {
state = {
...state,
deferPlayingEvent: true,
Expand Down Expand Up @@ -306,7 +306,7 @@ export const getMediaEventFilter = ({

const onPause = (): void => {
// playback ending should not trigger a pause event
if (videoElement.ended) return;
if (mediaElement.ended) return;
// Allow pausing while already paused if a play was requested
if (!state.playRequested && state.paused) return;

Expand All @@ -327,7 +327,7 @@ export const getMediaEventFilter = ({

callback(FilteredMediaEvent.LOADED);

if (videoElement.paused) {
if (mediaElement.paused) {
state = {
...state,
paused: true,
Expand All @@ -351,14 +351,14 @@ export const getMediaEventFilter = ({
// Not already buffering
!state.buffering &&
// playbackRate is 0
videoElement.playbackRate === 0 &&
// videoElement does not indicate it's seeking
!videoElement.seeking;
mediaElement.playbackRate === 0 &&
// mediaElement does not indicate it's seeking
!mediaElement.seeking;

const onRatechange = (): void => {
clearRatechangeBufferTimeout();

const playbackRateIsPositive = videoElement.playbackRate > 0;
const playbackRateIsPositive = mediaElement.playbackRate > 0;

// the engine kept buffering after "canplaythrough" event, recover
if (state.deferLoadedEvent && playbackRateIsPositive) {
Expand Down Expand Up @@ -427,7 +427,7 @@ export const getMediaEventFilter = ({
const onTimeupdate = (): void => {
if (isNotReady()) return;

if (state.buffering && !videoElement.paused) {
if (state.buffering && !mediaElement.paused) {
state = {
...state,
buffering: false,
Expand All @@ -453,15 +453,15 @@ export const getMediaEventFilter = ({
];

EventHandlerPairs.forEach(([event, handler]) =>
videoElement.addEventListener(event, handler),
mediaElement.addEventListener(event, handler),
);

return {
teardown: () => {
clearRatechangeBufferTimeout();

EventHandlerPairs.forEach(([event, handler]) =>
videoElement.removeEventListener(event, handler),
mediaElement.removeEventListener(event, handler),
);
},
};
Expand Down

0 comments on commit 5b502e9

Please sign in to comment.