happy-dom
Version:
Happy DOM is a JavaScript implementation of a web browser without its graphical user interface. It includes many web standards from WHATWG DOM and HTML.
683 lines • 19.2 kB
JavaScript
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const Event_js_1 = __importDefault(require("../../event/Event.cjs"));
const DOMExceptionNameEnum_js_1 = __importDefault(require("../../exception/DOMExceptionNameEnum.cjs"));
const HTMLElement_js_1 = __importDefault(require("../html-element/HTMLElement.cjs"));
const TimeRanges_js_1 = __importDefault(require("./TimeRanges.cjs"));
const DOMTokenList_js_1 = __importDefault(require("../../dom/DOMTokenList.cjs"));
const MediaStream_js_1 = __importDefault(require("./MediaStream.cjs"));
const TextTrackKindEnum_js_1 = __importDefault(require("./TextTrackKindEnum.cjs"));
const PropertySymbol = __importStar(require("../../PropertySymbol.cjs"));
/**
* HTML Media Element.
*
* Reference:
* https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement
*
*/
class HTMLMediaElement extends HTMLElement_js_1.default {
// Events
onabort = null;
oncanplay = null;
oncanplaythrough = null;
ondurationchange = null;
onemptied = null;
onended = null;
onerror = null;
onloadeddata = null;
onloadedmetadata = null;
onloadstart = null;
onpause = null;
onplay = null;
onplaying = null;
onprogress = null;
onratechange = null;
onresize = null;
onseeked = null;
onseeking = null;
onstalled = null;
onsuspend = null;
ontimeupdate = null;
onvolumechange = null;
onwaiting = null;
// 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_js_1.default(PropertySymbol.illegalConstructor);
[PropertySymbol.duration] = NaN;
[PropertySymbol.error] = null;
[PropertySymbol.ended] = false;
[PropertySymbol.networkState] = 0;
[PropertySymbol.readyState] = 0;
[PropertySymbol.seeking] = false;
[PropertySymbol.seekable] = new TimeRanges_js_1.default(PropertySymbol.illegalConstructor);
[PropertySymbol.sinkId] = '';
[PropertySymbol.played] = new TimeRanges_js_1.default(PropertySymbol.illegalConstructor);
[PropertySymbol.remote] = new this[PropertySymbol.window].RemotePlayback();
[PropertySymbol.controlsList] = null;
[PropertySymbol.mediaKeys] = null;
[PropertySymbol.srcObject] = null;
[PropertySymbol.textTracks] = [];
/**
* 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_js_1.default('canplay', { bubbles: false, cancelable: false }));
this.dispatchEvent(new Event_js_1.default('durationchange', { bubbles: false, cancelable: false }));
}
}
/**
* Returns controlsList.
*
* @returns ControlsList.
*/
get controlsList() {
if (this[PropertySymbol.controlsList] === null) {
this[PropertySymbol.controlsList] = new DOMTokenList_js_1.default(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_js_1.default)) {
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_js_1.default.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_js_1.default[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_js_1.default('pause', { bubbles: false, cancelable: false }));
}
/**
* Start playing media.
*/
async play() {
if (!this[PropertySymbol.paused]) {
return;
}
this[PropertySymbol.paused] = false;
this.dispatchEvent(new Event_js_1.default('play', { bubbles: false, cancelable: false }));
this.dispatchEvent(new Event_js_1.default('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_js_1.default('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);
}
}
exports.default = HTMLMediaElement;
//# sourceMappingURL=HTMLMediaElement.cjs.map