tiny-essentials
Version:
Collection of small, essential scripts designed to be used across various projects. These simple utilities are crafted for speed, ease of use, and versatility.
359 lines (309 loc) • 8.69 kB
JavaScript
'use strict';
var TinyHtmlTemplate = require('./TinyHtmlTemplate.cjs');
/** @typedef {import('./TinyHtmlTemplate.mjs').ClassSetter} ClassSetter */
/**
* TinyHtmlMedia is a base helper for <audio> and <video> elements.
* It provides a consistent API to control media playback and access
* standard {@link HTMLMediaElement} properties and methods.
*
* @template {HTMLMediaElement} TinyHtmlT
* @extends TinyHtmlTemplate<TinyHtmlT>
*/
class TinyHtmlMedia extends TinyHtmlTemplate {
/**
* Creates a new TinyHtmlMedia instance.
* @param {TinyHtmlT} tag - The HTML tag name (e.g., 'audio', 'video').
* @param {ClassSetter} [tags=[]] - Initial CSS classes to apply.
* @param {ClassSetter} [mainClass=[]] - Main CSS classes to apply.
*/
constructor(tag, tags = [], mainClass = []) {
super(tag, tags, mainClass);
}
// ------------------------
// Core playback controls
// ------------------------
/**
* Plays all attached media elements.
* @returns {Promise<void>} Resolves when all play calls complete.
*/
playMedia() {
return this.el.play();
}
/**
* Pauses all attached media elements.
* @returns {this}
*/
pauseMedia() {
this.el.pause();
return this;
}
/**
* Toggles play/pause state for all attached media elements.
* @returns {this}
*/
togglePlayMedia() {
const el = this.el;
el.paused ? el.play() : el.pause();
return this;
}
/**
* Stops all media by pausing and resetting the current time to `0`.
* @returns {this}
*/
stopMedia() {
this.pauseMedia();
this.currentTime = 0;
return this;
}
/**
* Reloads all attached media elements.
* @returns {this}
*/
loadMedia() {
this.el.load();
return this;
}
// ------------------------
// Methods
// ------------------------
/**
* Adds a new text track to the first media element.
* @param {TextTrackKind} kind - A string representing the TextTrack.kind property (subtitles, captions, descriptions, chapters, or metadata).
* @param {string} [label] - A string representing the TextTrack.label property.
* @param {string} [language] - A string representing the TextTrack.language property.
* @returns {TextTrack}
*/
addTextTrack(kind, label, language) {
return this.el.addTextTrack(kind, label, language);
}
/**
* Checks if a given MIME type can be played.
* @param {string} type - MIME type (e.g., 'video/mp4').
* @returns {CanPlayTypeResult} Either "", "probably", or "maybe".
*/
canPlayType(type) {
return this.el.canPlayType(type);
}
/**
* Seeks quickly to a given time if supported.
* @param {number} time - Target time in seconds.
* @returns {this}
*/
fastSeek(time) {
this.el.fastSeek(time);
return this;
}
/**
* Sets custom MediaKeys on the first media element.
* @param {MediaKeys|null} keys - Media keys to set.
* @returns {Promise<void>}
*/
setMediaKeys(keys) {
return this.el.setMediaKeys(keys);
}
/**
* Assigns a sink ID (output device) to the first media element.
* @param {string} id - The sink ID (device ID).
* @returns {Promise<void>}
*/
setSinkId(id) {
return this.el.setSinkId(id);
}
// ------------------------
// Properties (wrappers)
// ------------------------
/** @type {boolean} Autoplay state of the media. */
get autoplay() {
return this.el.autoplay;
}
set autoplay(v) {
this.setProp('autoplay', v);
}
/** @returns {TimeRanges} The buffered time ranges. */
get buffered() {
return this.el.buffered;
}
/** @type {boolean} Whether default controls are visible. */
get controls() {
return this.el.controls;
}
set controls(v) {
this.setProp('controls', v);
}
/** @type {string|null} The list of controls available. */
get controlsList() {
return this.attr('controlsList');
}
set controlsList(v) {
this.setAttr('controlsList', v);
}
/** @type {string|null} CORS setting for the media. */
get crossOrigin() {
return this.attr('crossOrigin');
}
set crossOrigin(v) {
this.setAttr('crossOrigin', v);
}
/** @returns {string} The resolved source URL currently playing. */
get currentSrc() {
return this.el.currentSrc;
}
/** @type {number} The current playback position in seconds. */
get currentTime() {
return this.el.currentTime;
}
set currentTime(t) {
this.el.currentTime = t;
}
/** @type {boolean} Whether media is muted by default. */
get defaultMuted() {
return this.el.defaultMuted;
}
set defaultMuted(v) {
this.setProp('defaultMuted', v);
}
/** @type {number} Default playback rate (1 = normal speed). */
get defaultPlaybackRate() {
return this.el.defaultPlaybackRate;
}
set defaultPlaybackRate(v) {
this.el.defaultPlaybackRate = v;
}
/** @type {boolean} Whether remote playback is disabled. */
get disableRemotePlayback() {
return this.el.disableRemotePlayback;
}
set disableRemotePlayback(v) {
this.setProp('disableRemotePlayback', v);
}
/** @returns {number} The duration of the media in seconds. */
get duration() {
return this.el.duration;
}
/** @returns {boolean} Whether the media has ended. */
get ended() {
return this.el.ended;
}
/** @returns {MediaError|null} Error state if media failed to load. */
get error() {
return this.el.error;
}
/** @type {boolean} Whether the media should loop. */
get loop() {
return this.el.loop;
}
set loop(v) {
this.setProp('loop', v);
}
/** @type {string|null} Media group name for synchronization. */
get mediaGroup() {
return this.attr('mediaGroup');
}
set mediaGroup(v) {
this.setAttr('mediaGroup', v);
}
/** @returns {MediaKeys|null} The associated MediaKeys object. */
get mediaKeys() {
return this.el.mediaKeys;
}
/** @type {boolean} Whether the media is muted. */
get muted() {
return this.el.muted;
}
set muted(state) {
this.el.muted = state;
}
/** @returns {number} Network state (see `HTMLMediaElement.networkState`). */
get networkState() {
return this.el.networkState;
}
/** @returns {boolean} Whether the media is currently paused. */
get paused() {
return this.el.paused;
}
/** @type {number} Current playback rate (1 = normal speed). */
get playbackRate() {
return this.el.playbackRate;
}
set playbackRate(rate) {
this.el.playbackRate = rate;
}
/** @returns {TimeRanges} Played time ranges. */
get played() {
return this.el.played;
}
/** @type {"" | "metadata" | "none" | "auto"} Preload strategy ('none', 'metadata', 'auto'). */
get preload() {
return this.el.preload;
}
set preload(v) {
const valid = ['auto', 'metadata', 'none'];
if (!valid.includes(v))
throw new TypeError(`TinyVideo: "preload" must be one of ${valid.join(', ')}.`);
this.setAttr('preload', v);
}
/** @type {boolean} Whether pitch is preserved when rate changes. */
get preservesPitch() {
return this.el.preservesPitch;
}
set preservesPitch(v) {
this.setProp('preservesPitch', v);
}
/** @returns {number} Ready state of the media. */
get readyState() {
return this.el.readyState;
}
/** @returns {RemotePlayback|null} Remote playback interface. */
get remote() {
return this.el.remote;
}
/** @returns {TimeRanges} Seekable time ranges. */
get seekable() {
return this.el.seekable;
}
/** @returns {boolean} Whether the media is currently seeking. */
get seeking() {
return this.el.seeking;
}
/** @returns {string} Current sink ID (output device). */
get sinkId() {
return this.el.sinkId;
}
/** @type {string|null} Source URL of the media. */
get src() {
return this.attr('src');
}
set src(v) {
this.setAttr('src', v);
}
/** @type {MediaProvider|null} Current `srcObject` (e.g., MediaStream). */
get srcObject() {
return this.el.srcObject;
}
set srcObject(v) {
this.el.srcObject = v;
}
/** @returns {TextTrackList} Available text tracks. */
get textTracks() {
return this.el.textTracks;
}
/**
* Gets the current volume.
* @returns {number} Value between 0.0 and 1.0.
*/
get volume() {
return this.el.volume;
}
/**
* Sets the volume level.
* @param {number} level - Value between 0.0 and 1.0.
* @throws {TypeError} If not a number.
*/
set volume(level) {
if (typeof level !== 'number' || level < 0 || level > 1) {
throw new TypeError('TinyVideo: "volume" must be a number between 0.0 and 1.0.');
}
this.el.volume = level;
}
}
module.exports = TinyHtmlMedia;