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.
287 lines (247 loc) • 8.96 kB
JavaScript
'use strict';
var TinyHtmlTemplate = require('./TinyHtmlTemplate.cjs');
/**
* {boolean} [config.fetchMode=TinyHtmlImage.#defaultFetchMode] - Whether to enable or disable fetch mode. Must be a boolean.
*/
/**
* TinyImage is a helper class for managing <img> elements.
* It supports modern attributes like srcset, sizes, decoding, fetchpriority,
* as well as width, height, alt, crossorigin, loading, and more.
*
* @example
* const img = new TinyHtmlImage({
* src: '/logo.png',
* alt: 'Logo',
* width: 200,
* height: 100,
* loading: 'lazy',
* decoding: 'async',
* });
*
* @extends TinyHtmlTemplate<HTMLImageElement>
*/
class TinyHtmlImage extends TinyHtmlTemplate {
/** @type {boolean} */
// static #defaultFetchMode = false;
/** @returns {boolean} */
// static get defaultFetchMode() {
// return TinyHtmlImage.#defaultFetchMode;
// }
/** @param {boolean} value */
// static set defaultFetchMode(value) {
// if (typeof value !== 'boolean')
// throw new TypeError('Expected a boolean value for defaultFetchMode');
// TinyHtmlImage.#defaultFetchMode = value;
// }
/** @type {boolean} */
// #fetchMode;
/** @returns {boolean} */
// get fetchMode() {
// return this.#fetchMode;
// }
/**
* Creates a new TinyHtmlImage instance wrapping an <img> element.
* This class simplifies working with images by providing a structured API
* for common attributes and configuration options.
*
* @param {Object} config - Image configuration object.
* @param {string} config.src - Image source URL (**required**).
* @param {string} [config.alt=""] - Alternate text for the image. Defaults to an empty string.
* @param {number} [config.width] - Width of the image in pixels.
* @param {number} [config.height] - Height of the image in pixels.
* @param {string|string[]|Set<string>} [config.tags=[]] - Initial CSS classes to apply.
* @param {string} [config.mainClass=""] - Main CSS class applied to the element.
* @param {string|string[]|boolean} [config.attributionsrc] - Attribution source; may be a string, array of strings, or `true/false`.
* @param {"anonymous"|"use-credentials"} [config.crossorigin] - Cross-origin policy for loading the image.
* @param {"sync"|"async"|"auto"} [config.decoding] - Decoding mode for the image.
* @param {string} [config.elementtiming] - Name used for performance timing attribution.
* @param {"high"|"low"|"auto"} [config.fetchpriority] - Fetch priority for the image resource.
* @param {boolean} [config.ismap=false] - Whether the image is part of a server-side image map.
* @param {"eager"|"lazy"} [config.loading] - Loading behavior hint (`"lazy"` defers off-screen images).
* @param {string} [config.referrerpolicy] - Referrer policy when fetching the image.
* @param {string} [config.sizes] - Sizes attribute, used with `srcset` for responsive images.
* @param {string} [config.srcset] - List of image sources for responsive loading.
* @param {string} [config.usemap] - Name of an associated image map to use.
*/
constructor({
src,
alt,
width,
height,
tags = [],
mainClass = '',
// fetchMode = TinyHtmlImage.#defaultFetchMode,
attributionsrc,
crossorigin,
decoding,
elementtiming,
fetchpriority,
ismap = false,
loading,
referrerpolicy,
sizes,
srcset,
usemap,
}) {
super(document.createElement('img'), tags, mainClass);
// required
this.src = src;
if (alt !== undefined) this.alt = alt;
if (width !== undefined) this.setWidth(width);
if (height !== undefined) this.setHeight(height);
if (attributionsrc !== undefined) this.attributionsrc = attributionsrc;
if (crossorigin !== undefined) this.crossorigin = crossorigin;
if (decoding !== undefined) this.decoding = decoding;
if (elementtiming !== undefined) this.elementtiming = elementtiming;
if (fetchpriority !== undefined) this.fetchpriority = fetchpriority;
this.ismap = ismap;
if (loading !== undefined) this.loading = loading;
if (referrerpolicy !== undefined) this.referrerpolicy = referrerpolicy;
if (sizes !== undefined) this.sizes = sizes;
if (srcset !== undefined) this.srcset = srcset;
if (usemap !== undefined) this.usemap = usemap;
// if (typeof fetchMode !== 'boolean')
// throw new TypeError('TinyImage: "fetchMode" must be a boolean.');
// this.#fetchMode = fetchMode;
}
// --- Attributes ---
/** @param {string} value */
set src(value) {
if (typeof value !== 'string') throw new TypeError('TinyImage: "src" must be a string.');
this.setAttr('src', value);
}
/** @returns {string|null} */
get src() {
return this.attrString('src');
}
/** @param {string} value */
set alt(value) {
if (typeof value !== 'string') throw new TypeError('TinyImage: "alt" must be a string.');
this.setAttr('alt', value);
}
/** @returns {string|null} */
get alt() {
return this.attrString('alt');
}
/** @param {string|string[]|boolean} value */
set attributionsrc(value) {
if (typeof value === 'boolean') {
if (value) this.addProp('attributionsrc');
else this.removeProp('attributionsrc');
return;
}
if (typeof value === 'string') {
this.setAttr('attributionsrc', value);
return;
}
if (Array.isArray(value)) {
this.setAttr('attributionsrc', value.join(','));
return;
}
throw new TypeError(
'TinyImage: "attributionsrc" must be a boolean, string, or array of strings.',
);
}
/** @returns {string|null} */
get attributionsrc() {
return this.attrString('attributionsrc');
}
/** @param {'anonymous'|'use-credentials'} value */
set crossorigin(value) {
if (!['anonymous', 'use-credentials'].includes(value))
throw new TypeError('TinyImage: "crossorigin" must be "anonymous" or "use-credentials".');
this.setAttr('crossorigin', value);
}
/** @returns {string|null} */
get crossorigin() {
return this.attrString('crossorigin');
}
/** @param {'sync'|'async'|'auto'} value */
set decoding(value) {
if (!['sync', 'async', 'auto'].includes(value))
throw new TypeError('TinyImage: "decoding" must be "sync", "async" or "auto".');
this.setAttr('decoding', value);
}
/** @returns {string|null} */
get decoding() {
return this.attrString('decoding');
}
/** @param {string} value */
set elementtiming(value) {
if (typeof value !== 'string')
throw new TypeError('TinyImage: "elementtiming" must be a string.');
this.setAttr('elementtiming', value);
}
/** @returns {string|null} */
get elementtiming() {
return this.attrString('elementtiming');
}
/** @param {'high'|'low'|'auto'} value */
set fetchpriority(value) {
if (!['high', 'low', 'auto'].includes(value))
throw new TypeError('TinyImage: "fetchpriority" must be "high", "low" or "auto".');
this.setAttr('fetchpriority', value);
}
/** @returns {string|null} */
get fetchpriority() {
return this.attrString('fetchpriority');
}
/** @param {boolean} value */
set ismap(value) {
if (typeof value !== 'boolean') throw new TypeError('TinyImage: "ismap" must be a boolean.');
if (value) this.addProp('ismap');
else this.removeProp('ismap');
}
/** @returns {boolean} */
get ismap() {
return this.hasProp('ismap');
}
/** @param {'eager'|'lazy'} value */
set loading(value) {
if (!['eager', 'lazy'].includes(value))
throw new TypeError('TinyImage: "loading" must be "eager" or "lazy".');
this.setAttr('loading', value);
}
/** @returns {string|null} */
get loading() {
return this.attrString('loading');
}
/** @param {string} value */
set referrerpolicy(value) {
if (typeof value !== 'string')
throw new TypeError('TinyImage: "referrerpolicy" must be a string.');
this.setAttr('referrerpolicy', value);
}
/** @returns {string|null} */
get referrerpolicy() {
return this.attrString('referrerpolicy');
}
/** @param {string} value */
set sizes(value) {
if (typeof value !== 'string') throw new TypeError('TinyImage: "sizes" must be a string.');
this.setAttr('sizes', value);
}
/** @returns {string|null} */
get sizes() {
return this.attrString('sizes');
}
/** @param {string} value */
set srcset(value) {
if (typeof value !== 'string') throw new TypeError('TinyImage: "srcset" must be a string.');
this.setAttr('srcset', value);
}
/** @returns {string|null} */
get srcset() {
return this.attrString('srcset');
}
/** @param {string} value */
set usemap(value) {
if (typeof value !== 'string') throw new TypeError('TinyImage: "usemap" must be a string.');
this.setAttr('usemap', value);
}
/** @returns {string|null} */
get usemap() {
return this.attrString('usemap');
}
}
module.exports = TinyHtmlImage;