In my expectation, I wish to use MutationObserver to listen to the event that tells the video has loaded. The reason for that is I need to add a loading animation before the video has been rendered and loaded in the DOM, then remove the animation when the video showed on the page. It seems that MutationObserver couldn't tell the time when the video loaded, it only knows the attributes changed.
Below is my code:
const callback = () => {
console.log('done')
}
const observer = new MutationObserver(callback)
this.observer.observe(videoNode, {
attributes: true
})
In my expectation, I wish to use
MutationObserverto listen to the event that tells the video has loaded. The reason for that is I need to add a loading animation before the video has been rendered and loaded in the DOM, then remove the animation when the video showed on the page. It seems thatMutationObservercouldn't tell the time when the video loaded, it only knows the attributes changed. below is my code.
Why are you MutationObserver for this when HTMLVideoElement already has a load event and and readyState properties that tell you this exact information? (Though you probably should use the canplay or the loadeddata events instead of load).
Using MutationObserver won't work anyway because it's for observing structural changes to the DOM tree (e.g. adding/removing elements and attributes, but not object properties), so it won't observe changes to DOM properties that are independent of DOM attributes (as element attributes do not map 1:1 to object properties, this also applies to CSS: you can set disabled on HTMLInputElement and the :disabled psuedo-class will work, but it won't match the [disabled] attribute selector).
All you need is this:
// https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/readyState
const READYSTATE_HAVE_NOTHING = 0;
const READYSTATE_HAVE_METADATA = 1;
const READYSTATE_HAVE_CURRENT_DATA = 2;
const READYSTATE_HAVE_FUTURE_DATA = 3;
const READYSTATE_HAVE_ENOUGH_DATA = 4;
const videoElement = document.querySelector( 'video#someId' );
if( !videoElement ) throw new Error( "Couldn't find <video> element." );
if( videoElement.readyState === READYSTATE_HAVE_ENOUGH_DATA ) {
// If the video is already loaded, don't do anything.
}
else {
// Else, show the spinner and remove it after it's loaded:
const spinner = document.createElement('div');
spinner.classList.add('spinner');
videoElement.parent.appendChild( spinner );
videoElement.addEventListener( 'canplay', function() {
document.querySelector('.spinner')?.remove();
} );
}