- Delete old Vite+Svelte frontend - Initialize new SvelteKit project with TypeScript - Configure Tailwind CSS v4 + DaisyUI - Implement JWT authentication with auto-refresh - Create login page with form validation (Zod) - Add protected route guards - Update Docker configuration for single-stage build - Add E2E tests with Playwright (6/11 passing) - Fix Svelte 5 reactivity with $state() runes Known issues: - 5 E2E tests failing (timing/async issues) - Token refresh implementation needs debugging - Validation error display timing
766 lines
22 KiB
JavaScript
766 lines
22 KiB
JavaScript
import Event from '../../event/Event.js';
|
|
import DOMExceptionNameEnum from '../../exception/DOMExceptionNameEnum.js';
|
|
import HTMLElement from '../html-element/HTMLElement.js';
|
|
import TimeRanges from './TimeRanges.js';
|
|
import DOMTokenList from '../../dom/DOMTokenList.js';
|
|
import MediaStream from './MediaStream.js';
|
|
import TextTrackKindEnum from './TextTrackKindEnum.js';
|
|
import * as PropertySymbol from '../../PropertySymbol.js';
|
|
import ElementEventAttributeUtility from '../element/ElementEventAttributeUtility.js';
|
|
/**
|
|
* HTML Media Element.
|
|
*
|
|
* Reference:
|
|
* https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement
|
|
*
|
|
*/
|
|
export default class HTMLMediaElement extends HTMLElement {
|
|
// Internal Properties
|
|
[PropertySymbol.volume] = 1;
|
|
[PropertySymbol.paused] = true;
|
|
[PropertySymbol.currentTime] = 0;
|
|
[PropertySymbol.playbackRate] = 1;
|
|
[PropertySymbol.defaultPlaybackRate] = 1;
|
|
[PropertySymbol.muted] = false;
|
|
[PropertySymbol.defaultMuted] = false;
|
|
[PropertySymbol.preservesPitch] = true;
|
|
[PropertySymbol.buffered] = new TimeRanges(PropertySymbol.illegalConstructor);
|
|
[PropertySymbol.duration] = NaN;
|
|
[PropertySymbol.error] = null;
|
|
[PropertySymbol.ended] = false;
|
|
[PropertySymbol.networkState] = 0;
|
|
[PropertySymbol.readyState] = 0;
|
|
[PropertySymbol.seeking] = false;
|
|
[PropertySymbol.seekable] = new TimeRanges(PropertySymbol.illegalConstructor);
|
|
[PropertySymbol.sinkId] = '';
|
|
[PropertySymbol.played] = new TimeRanges(PropertySymbol.illegalConstructor);
|
|
[PropertySymbol.remote] = new this[PropertySymbol.window].RemotePlayback();
|
|
[PropertySymbol.controlsList] = null;
|
|
[PropertySymbol.mediaKeys] = null;
|
|
[PropertySymbol.srcObject] = null;
|
|
[PropertySymbol.textTracks] = [];
|
|
// Events
|
|
/* eslint-disable jsdoc/require-jsdoc */
|
|
get onabort() {
|
|
return ElementEventAttributeUtility.getEventListener(this, 'onabort');
|
|
}
|
|
set onabort(value) {
|
|
this[PropertySymbol.propertyEventListeners].set('onabort', value);
|
|
}
|
|
get oncanplay() {
|
|
return ElementEventAttributeUtility.getEventListener(this, 'oncanplay');
|
|
}
|
|
set oncanplay(value) {
|
|
this[PropertySymbol.propertyEventListeners].set('oncanplay', value);
|
|
}
|
|
get oncanplaythrough() {
|
|
return ElementEventAttributeUtility.getEventListener(this, 'oncanplaythrough');
|
|
}
|
|
set oncanplaythrough(value) {
|
|
this[PropertySymbol.propertyEventListeners].set('oncanplaythrough', value);
|
|
}
|
|
get ondurationchange() {
|
|
return ElementEventAttributeUtility.getEventListener(this, 'ondurationchange');
|
|
}
|
|
set ondurationchange(value) {
|
|
this[PropertySymbol.propertyEventListeners].set('ondurationchange', value);
|
|
}
|
|
get onemptied() {
|
|
return ElementEventAttributeUtility.getEventListener(this, 'onemptied');
|
|
}
|
|
set onemptied(value) {
|
|
this[PropertySymbol.propertyEventListeners].set('onemptied', value);
|
|
}
|
|
get onended() {
|
|
return ElementEventAttributeUtility.getEventListener(this, 'onended');
|
|
}
|
|
set onended(value) {
|
|
this[PropertySymbol.propertyEventListeners].set('onended', value);
|
|
}
|
|
get onloadeddata() {
|
|
return ElementEventAttributeUtility.getEventListener(this, 'onloadeddata');
|
|
}
|
|
set onloadeddata(value) {
|
|
this[PropertySymbol.propertyEventListeners].set('onloadeddata', value);
|
|
}
|
|
get onloadedmetadata() {
|
|
return ElementEventAttributeUtility.getEventListener(this, 'onloadedmetadata');
|
|
}
|
|
set onloadedmetadata(value) {
|
|
this[PropertySymbol.propertyEventListeners].set('onloadedmetadata', value);
|
|
}
|
|
get onloadstart() {
|
|
return ElementEventAttributeUtility.getEventListener(this, 'onloadstart');
|
|
}
|
|
set onloadstart(value) {
|
|
this[PropertySymbol.propertyEventListeners].set('onloadstart', value);
|
|
}
|
|
get onpause() {
|
|
return ElementEventAttributeUtility.getEventListener(this, 'onpause');
|
|
}
|
|
set onpause(value) {
|
|
this[PropertySymbol.propertyEventListeners].set('onpause', value);
|
|
}
|
|
get onplay() {
|
|
return ElementEventAttributeUtility.getEventListener(this, 'onplay');
|
|
}
|
|
set onplay(value) {
|
|
this[PropertySymbol.propertyEventListeners].set('onplay', value);
|
|
}
|
|
get onplaying() {
|
|
return ElementEventAttributeUtility.getEventListener(this, 'onplaying');
|
|
}
|
|
set onplaying(value) {
|
|
this[PropertySymbol.propertyEventListeners].set('onplaying', value);
|
|
}
|
|
get onprogress() {
|
|
return ElementEventAttributeUtility.getEventListener(this, 'onprogress');
|
|
}
|
|
set onprogress(value) {
|
|
this[PropertySymbol.propertyEventListeners].set('onprogress', value);
|
|
}
|
|
get onratechange() {
|
|
return ElementEventAttributeUtility.getEventListener(this, 'onratechange');
|
|
}
|
|
set onratechange(value) {
|
|
this[PropertySymbol.propertyEventListeners].set('onratechange', value);
|
|
}
|
|
get onresize() {
|
|
return ElementEventAttributeUtility.getEventListener(this, 'onresize');
|
|
}
|
|
set onresize(value) {
|
|
this[PropertySymbol.propertyEventListeners].set('onresize', value);
|
|
}
|
|
get onseeked() {
|
|
return ElementEventAttributeUtility.getEventListener(this, 'onseeked');
|
|
}
|
|
set onseeked(value) {
|
|
this[PropertySymbol.propertyEventListeners].set('onseeked', value);
|
|
}
|
|
get onseeking() {
|
|
return ElementEventAttributeUtility.getEventListener(this, 'onseeking');
|
|
}
|
|
set onseeking(value) {
|
|
this[PropertySymbol.propertyEventListeners].set('onseeking', value);
|
|
}
|
|
get onstalled() {
|
|
return ElementEventAttributeUtility.getEventListener(this, 'onstalled');
|
|
}
|
|
set onstalled(value) {
|
|
this[PropertySymbol.propertyEventListeners].set('onstalled', value);
|
|
}
|
|
get onsuspend() {
|
|
return ElementEventAttributeUtility.getEventListener(this, 'onsuspend');
|
|
}
|
|
set onsuspend(value) {
|
|
this[PropertySymbol.propertyEventListeners].set('onsuspend', value);
|
|
}
|
|
get ontimeupdate() {
|
|
return ElementEventAttributeUtility.getEventListener(this, 'ontimeupdate');
|
|
}
|
|
set ontimeupdate(value) {
|
|
this[PropertySymbol.propertyEventListeners].set('ontimeupdate', value);
|
|
}
|
|
get onvolumechange() {
|
|
return ElementEventAttributeUtility.getEventListener(this, 'onvolumechange');
|
|
}
|
|
set onvolumechange(value) {
|
|
this[PropertySymbol.propertyEventListeners].set('onvolumechange', value);
|
|
}
|
|
get onwaiting() {
|
|
return ElementEventAttributeUtility.getEventListener(this, 'onwaiting');
|
|
}
|
|
set onwaiting(value) {
|
|
this[PropertySymbol.propertyEventListeners].set('onwaiting', value);
|
|
}
|
|
/* eslint-enable jsdoc/require-jsdoc */
|
|
/**
|
|
* Returns buffered.
|
|
*
|
|
* @returns Buffered.
|
|
*/
|
|
get buffered() {
|
|
return this[PropertySymbol.buffered];
|
|
}
|
|
/**
|
|
* Returns duration.
|
|
*
|
|
* @returns Duration.
|
|
*/
|
|
get duration() {
|
|
return this[PropertySymbol.duration];
|
|
}
|
|
/**
|
|
* Returns error.
|
|
*
|
|
* @returns Error.
|
|
*/
|
|
get error() {
|
|
return this[PropertySymbol.error];
|
|
}
|
|
/**
|
|
* Returns ended.
|
|
*
|
|
* @returns Ended.
|
|
*/
|
|
get ended() {
|
|
return this[PropertySymbol.ended];
|
|
}
|
|
/**
|
|
* Returns networkState.
|
|
*
|
|
* @returns NetworkState.
|
|
*/
|
|
get networkState() {
|
|
return this[PropertySymbol.networkState];
|
|
}
|
|
/**
|
|
* Returns readyState.
|
|
*
|
|
* @returns ReadyState.
|
|
*/
|
|
get readyState() {
|
|
return this[PropertySymbol.readyState];
|
|
}
|
|
/**
|
|
* Return a RemotePlayback object instance associated with the media element.
|
|
*
|
|
* @returns RemotePlayback.
|
|
*/
|
|
get remote() {
|
|
return this[PropertySymbol.remote];
|
|
}
|
|
/**
|
|
* Returns seeking.
|
|
*
|
|
* @returns Seeking.
|
|
*/
|
|
get seeking() {
|
|
return this[PropertySymbol.seeking];
|
|
}
|
|
/**
|
|
* Returns seekable.
|
|
*
|
|
* @returns Seekable.
|
|
*/
|
|
get seekable() {
|
|
return this[PropertySymbol.seekable];
|
|
}
|
|
/**
|
|
* Returns sinkId.
|
|
*
|
|
* @returns SinkId.
|
|
*/
|
|
get sinkId() {
|
|
return this[PropertySymbol.sinkId];
|
|
}
|
|
/**
|
|
* Returns played.
|
|
*
|
|
* @returns Played.
|
|
*/
|
|
get played() {
|
|
return this[PropertySymbol.played];
|
|
}
|
|
/**
|
|
* Returns autoplay.
|
|
*
|
|
* @returns Autoplay.
|
|
*/
|
|
get autoplay() {
|
|
return this.getAttribute('autoplay') !== null;
|
|
}
|
|
/**
|
|
* Sets autoplay.
|
|
*
|
|
* @param autoplay Autoplay.
|
|
*/
|
|
set autoplay(autoplay) {
|
|
if (!autoplay) {
|
|
this.removeAttribute('autoplay');
|
|
}
|
|
else {
|
|
this.setAttribute('autoplay', '');
|
|
}
|
|
}
|
|
/**
|
|
* Returns controls.
|
|
*
|
|
* @returns Controls.
|
|
*/
|
|
get controls() {
|
|
return this.getAttribute('controls') !== null;
|
|
}
|
|
/**
|
|
* Sets controls.
|
|
*
|
|
* @param controls Controls.
|
|
*/
|
|
set controls(controls) {
|
|
if (!controls) {
|
|
this.removeAttribute('controls');
|
|
}
|
|
else {
|
|
this.setAttribute('controls', '');
|
|
}
|
|
}
|
|
/**
|
|
* Returns loop.
|
|
*
|
|
* @returns Loop.
|
|
*/
|
|
get loop() {
|
|
return this.getAttribute('loop') !== null;
|
|
}
|
|
/**
|
|
* Sets loop.
|
|
*
|
|
* @param loop Loop.
|
|
*/
|
|
set loop(loop) {
|
|
if (!loop) {
|
|
this.removeAttribute('loop');
|
|
}
|
|
else {
|
|
this.setAttribute('loop', '');
|
|
}
|
|
}
|
|
/**
|
|
* Returns preload.
|
|
*
|
|
* @returns preload.
|
|
*/
|
|
get preload() {
|
|
return this.getAttribute('preload') || 'auto';
|
|
}
|
|
/**
|
|
* Sets preload.
|
|
*
|
|
* @param preload preload.
|
|
*/
|
|
set preload(preload) {
|
|
this.setAttribute('preload', preload);
|
|
}
|
|
/**
|
|
* Returns src.
|
|
*
|
|
* @returns Src.
|
|
*/
|
|
get src() {
|
|
if (!this.hasAttribute('src')) {
|
|
return '';
|
|
}
|
|
try {
|
|
return new URL(this.getAttribute('src'), this[PropertySymbol.ownerDocument].location.href)
|
|
.href;
|
|
}
|
|
catch (e) {
|
|
return this.getAttribute('src');
|
|
}
|
|
}
|
|
/**
|
|
* Sets src.
|
|
*
|
|
* @param src Src.
|
|
*/
|
|
set src(src) {
|
|
this.setAttribute('src', src);
|
|
if (Boolean(src)) {
|
|
this.dispatchEvent(new Event('canplay', { bubbles: false, cancelable: false }));
|
|
this.dispatchEvent(new Event('durationchange', { bubbles: false, cancelable: false }));
|
|
}
|
|
}
|
|
/**
|
|
* Returns controlsList.
|
|
*
|
|
* @returns ControlsList.
|
|
*/
|
|
get controlsList() {
|
|
if (this[PropertySymbol.controlsList] === null) {
|
|
this[PropertySymbol.controlsList] = new DOMTokenList(PropertySymbol.illegalConstructor, this, 'controlslist');
|
|
}
|
|
return this[PropertySymbol.controlsList];
|
|
}
|
|
/**
|
|
* Sets controlsList.
|
|
*
|
|
* @param value Value.
|
|
*/
|
|
set controlsList(value) {
|
|
this.setAttribute('controlslist', value);
|
|
}
|
|
/**
|
|
* Returns mediaKeys.
|
|
*
|
|
* @returns MediaKeys.
|
|
*/
|
|
get mediaKeys() {
|
|
return this[PropertySymbol.mediaKeys];
|
|
}
|
|
/**
|
|
* Returns muted.
|
|
*
|
|
* @returns Muted.
|
|
*/
|
|
get muted() {
|
|
if (this[PropertySymbol.muted]) {
|
|
return this[PropertySymbol.muted];
|
|
}
|
|
if (!this[PropertySymbol.defaultMuted]) {
|
|
return this.getAttribute('muted') !== null;
|
|
}
|
|
return false;
|
|
}
|
|
/**
|
|
* Sets muted.
|
|
*
|
|
* @param muted Muted.
|
|
*/
|
|
set muted(muted) {
|
|
this[PropertySymbol.muted] = !!muted;
|
|
if (!muted && !this[PropertySymbol.defaultMuted]) {
|
|
this.removeAttribute('muted');
|
|
}
|
|
else {
|
|
this.setAttribute('muted', '');
|
|
}
|
|
}
|
|
/**
|
|
* Returns defaultMuted.
|
|
*
|
|
* @returns DefaultMuted.
|
|
*/
|
|
get defaultMuted() {
|
|
return this[PropertySymbol.defaultMuted];
|
|
}
|
|
/**
|
|
* Sets defaultMuted.
|
|
*
|
|
* @param defaultMuted DefaultMuted.
|
|
*/
|
|
set defaultMuted(defaultMuted) {
|
|
this[PropertySymbol.defaultMuted] = !!defaultMuted;
|
|
if (!this[PropertySymbol.defaultMuted] && !this[PropertySymbol.muted]) {
|
|
this.removeAttribute('muted');
|
|
}
|
|
else {
|
|
this.setAttribute('muted', '');
|
|
}
|
|
}
|
|
/**
|
|
* Returns disableRemotePlayback.
|
|
*
|
|
* @returns DisableRemotePlayback.
|
|
*/
|
|
get disableRemotePlayback() {
|
|
return this.getAttribute('disableremoteplayback') !== null;
|
|
}
|
|
/**
|
|
* Sets disableRemotePlayback.
|
|
*
|
|
* @param disableRemotePlayback DisableRemotePlayback.
|
|
*/
|
|
set disableRemotePlayback(disableRemotePlayback) {
|
|
if (!disableRemotePlayback) {
|
|
this.removeAttribute('disableremoteplayback');
|
|
}
|
|
else {
|
|
this.setAttribute('disableremoteplayback', '');
|
|
}
|
|
}
|
|
/**
|
|
* A MediaStream representing the media to play or that has played in the current HTMLMediaElement, or null if not assigned.
|
|
*
|
|
* @returns MediaStream.
|
|
*/
|
|
get srcObject() {
|
|
return this[PropertySymbol.srcObject];
|
|
}
|
|
/**
|
|
* Sets src object.
|
|
*
|
|
* @param srcObject SrcObject.
|
|
*/
|
|
set srcObject(srcObject) {
|
|
if (srcObject !== null && !(srcObject instanceof MediaStream)) {
|
|
throw new this[PropertySymbol.window].TypeError(`Failed to set the 'srcObject' property on 'HTMLMediaElement': The provided value is not of type 'MediaStream'.`);
|
|
}
|
|
this[PropertySymbol.srcObject] = srcObject;
|
|
}
|
|
/**
|
|
* Returns text track list.
|
|
*
|
|
* @returns Text track list.
|
|
*/
|
|
get textTracks() {
|
|
const items = [];
|
|
for (const track of this[PropertySymbol.textTracks]) {
|
|
items.push(track);
|
|
}
|
|
for (const track of this.querySelectorAll('track')[PropertySymbol.items]) {
|
|
items.push(track.track);
|
|
}
|
|
return new this[PropertySymbol.window].TextTrackList(PropertySymbol.illegalConstructor, items);
|
|
}
|
|
/**
|
|
* Returns currentSrc.
|
|
*
|
|
* @returns CurrentrSrc.
|
|
*/
|
|
get currentSrc() {
|
|
const src = this.src;
|
|
if (src) {
|
|
return src;
|
|
}
|
|
const sourceElement = this.querySelector('source');
|
|
return sourceElement ? sourceElement.src : '';
|
|
}
|
|
/**
|
|
* Returns volume.
|
|
*
|
|
* @returns Volume.
|
|
*/
|
|
get volume() {
|
|
return this[PropertySymbol.volume];
|
|
}
|
|
/**
|
|
* Sets volume.
|
|
*
|
|
* @param volume Volume.
|
|
*/
|
|
set volume(volume) {
|
|
const parsedVolume = Number(volume);
|
|
if (isNaN(parsedVolume)) {
|
|
throw new this[PropertySymbol.window].TypeError(`Failed to set the 'volume' property on 'HTMLMediaElement': The provided double value is non-finite.`);
|
|
}
|
|
if (parsedVolume < 0 || parsedVolume > 1) {
|
|
throw new this[PropertySymbol.window].DOMException(`Failed to set the 'volume' property on 'HTMLMediaElement': The volume provided (${parsedVolume}) is outside the range [0, 1].`, DOMExceptionNameEnum.indexSizeError);
|
|
}
|
|
// TODO: volumechange event https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/volumechange_event
|
|
this[PropertySymbol.volume] = parsedVolume;
|
|
}
|
|
/**
|
|
* Returns crossOrigin.
|
|
*
|
|
* @returns CrossOrigin.
|
|
*/
|
|
get crossOrigin() {
|
|
const crossOrigin = this.getAttribute('crossorigin');
|
|
if (crossOrigin === 'use-credentials') {
|
|
return 'use-credentials';
|
|
}
|
|
if (crossOrigin !== null) {
|
|
return 'anonymous';
|
|
}
|
|
return null;
|
|
}
|
|
/**
|
|
* Sets crossOrigin.
|
|
*
|
|
* @param crossOrigin CrossOrigin.
|
|
*/
|
|
set crossOrigin(crossOrigin) {
|
|
this.setAttribute('crossorigin', crossOrigin);
|
|
}
|
|
/**
|
|
* Returns currentTime.
|
|
*
|
|
* @returns CurrentTime.
|
|
*/
|
|
get currentTime() {
|
|
return this[PropertySymbol.currentTime];
|
|
}
|
|
/**
|
|
* Sets currentTime.
|
|
*
|
|
* @param currentTime CurrentTime.
|
|
*/
|
|
set currentTime(currentTime) {
|
|
const parsedCurrentTime = Number(currentTime);
|
|
if (isNaN(parsedCurrentTime)) {
|
|
throw new this[PropertySymbol.window].TypeError(`Failed to set the 'currentTime' property on 'HTMLMediaElement': The provided double value is non-finite.`);
|
|
}
|
|
this[PropertySymbol.currentTime] = parsedCurrentTime;
|
|
}
|
|
/**
|
|
* Returns playbackRate.
|
|
*
|
|
* @returns PlaybackRate.
|
|
*/
|
|
get playbackRate() {
|
|
return this[PropertySymbol.playbackRate];
|
|
}
|
|
/**
|
|
* Sets playbackRate.
|
|
*
|
|
* @param playbackRate PlaybackRate.
|
|
*/
|
|
set playbackRate(playbackRate) {
|
|
const parsedPlaybackRate = Number(playbackRate);
|
|
if (isNaN(parsedPlaybackRate)) {
|
|
throw new this[PropertySymbol.window].TypeError(`Failed to set the 'playbackRate' property on 'HTMLMediaElement': The provided double value is non-finite.`);
|
|
}
|
|
this[PropertySymbol.playbackRate] = parsedPlaybackRate;
|
|
}
|
|
/**
|
|
* Returns defaultPlaybackRate.
|
|
*
|
|
* @returns DefaultPlaybackRate.
|
|
*/
|
|
get defaultPlaybackRate() {
|
|
return this[PropertySymbol.defaultPlaybackRate];
|
|
}
|
|
/**
|
|
* Sets defaultPlaybackRate.
|
|
*
|
|
* @param defaultPlaybackRate DefaultPlaybackRate.
|
|
*/
|
|
set defaultPlaybackRate(defaultPlaybackRate) {
|
|
const parsedDefaultPlaybackRate = Number(defaultPlaybackRate);
|
|
if (isNaN(parsedDefaultPlaybackRate)) {
|
|
throw new this[PropertySymbol.window].TypeError(`Failed to set the 'defaultPlaybackRate' property on 'HTMLMediaElement': The provided double value is non-finite.`);
|
|
}
|
|
this[PropertySymbol.defaultPlaybackRate] = parsedDefaultPlaybackRate;
|
|
}
|
|
/**
|
|
* Returns preservesPitch.
|
|
*
|
|
* @returns PlaybackRate.
|
|
*/
|
|
get preservesPitch() {
|
|
return this[PropertySymbol.preservesPitch];
|
|
}
|
|
/**
|
|
* Sets preservesPitch.
|
|
*
|
|
* @param preservesPitch PreservesPitch.
|
|
*/
|
|
set preservesPitch(preservesPitch) {
|
|
this[PropertySymbol.preservesPitch] = Boolean(preservesPitch);
|
|
}
|
|
/**
|
|
* Returns paused.
|
|
*
|
|
* @returns Paused.
|
|
*/
|
|
get paused() {
|
|
return this[PropertySymbol.paused];
|
|
}
|
|
/**
|
|
* @override
|
|
*/
|
|
get tabIndex() {
|
|
const tabIndex = this.getAttribute('tabindex');
|
|
if (tabIndex !== null) {
|
|
const parsed = Number(tabIndex);
|
|
return isNaN(parsed) ? 0 : parsed;
|
|
}
|
|
return 0;
|
|
}
|
|
/**
|
|
* @override
|
|
*/
|
|
set tabIndex(tabIndex) {
|
|
super.tabIndex = tabIndex;
|
|
}
|
|
/**
|
|
* Adds a new text track to the media element.
|
|
*
|
|
* @param kind The kind of text track.
|
|
* @param label The label of the text track.
|
|
* @param language The language of the text track data.
|
|
*/
|
|
addTextTrack(kind, label, language) {
|
|
const window = this[PropertySymbol.window];
|
|
if (arguments.length === 0) {
|
|
throw new window.TypeError(`Failed to execute 'addTextTrack' on 'HTMLMediaElement': 1 argument required, but only 0 present.`);
|
|
}
|
|
if (!TextTrackKindEnum[kind]) {
|
|
throw new window.TypeError(`Failed to execute 'addTextTrack' on 'HTMLMediaElement': The provided value '${kind}' is not a valid enum value of type TextTrackKind.`);
|
|
}
|
|
const track = new window.TextTrack(PropertySymbol.illegalConstructor);
|
|
track[PropertySymbol.kind] = kind;
|
|
track[PropertySymbol.label] = label || '';
|
|
track[PropertySymbol.language] = language || '';
|
|
this[PropertySymbol.textTracks].push(track);
|
|
return track;
|
|
}
|
|
/**
|
|
* Pause played media.
|
|
*/
|
|
pause() {
|
|
if (this[PropertySymbol.paused]) {
|
|
return;
|
|
}
|
|
this[PropertySymbol.paused] = true;
|
|
this.dispatchEvent(new Event('pause', { bubbles: false, cancelable: false }));
|
|
}
|
|
/**
|
|
* Start playing media.
|
|
*/
|
|
async play() {
|
|
if (!this[PropertySymbol.paused]) {
|
|
return;
|
|
}
|
|
this[PropertySymbol.paused] = false;
|
|
this.dispatchEvent(new Event('play', { bubbles: false, cancelable: false }));
|
|
this.dispatchEvent(new Event('playing', { bubbles: false, cancelable: false }));
|
|
}
|
|
/**
|
|
* Reports how likely it is that the current browser will be able to play media of a given MIME type.
|
|
*
|
|
* @param _type MIME type.
|
|
* @returns Can play type.
|
|
*/
|
|
canPlayType(_type) {
|
|
// TODO: Implement this method
|
|
return '';
|
|
}
|
|
/**
|
|
* Quickly seeks the media to the new time with precision tradeoff.
|
|
*
|
|
* @param _time Time.
|
|
*/
|
|
fastSeek(_time) {
|
|
// TODO: Implement this method
|
|
}
|
|
/**
|
|
* Load media.
|
|
*/
|
|
load() {
|
|
this.dispatchEvent(new Event('emptied', { bubbles: false, cancelable: false }));
|
|
}
|
|
/**
|
|
* Sets media keys.
|
|
*
|
|
* @param mediaKeys MediaKeys.
|
|
* @returns Promise.
|
|
*/
|
|
async setMediaKeys(mediaKeys) {
|
|
this[PropertySymbol.mediaKeys] = mediaKeys;
|
|
}
|
|
/**
|
|
* Sets sink id.
|
|
*
|
|
* @param sinkId SinkId.
|
|
* @returns Promise.
|
|
*/
|
|
async setSinkId(sinkId) {
|
|
this[PropertySymbol.sinkId] = sinkId;
|
|
}
|
|
/**
|
|
* Returns MediaStream, captures a stream of the media content.
|
|
*
|
|
* @returns MediaStream.
|
|
*/
|
|
captureStream() {
|
|
return new this[PropertySymbol.window].MediaStream();
|
|
}
|
|
/**
|
|
* @override
|
|
*/
|
|
[PropertySymbol.cloneNode](deep = false) {
|
|
return super[PropertySymbol.cloneNode](deep);
|
|
}
|
|
}
|
|
//# sourceMappingURL=HTMLMediaElement.js.map
|