tiny-essentials 1.20.0 → 1.20.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/v1/TinyBasicsEs.min.js +1 -1
- package/dist/v1/TinyDragger.min.js +1 -1
- package/dist/v1/TinyEssentials.min.js +1 -1
- package/dist/v1/TinyHtml.min.js +1 -1
- package/dist/v1/TinySmartScroller.min.js +1 -1
- package/dist/v1/TinyUploadClicker.min.js +1 -1
- package/dist/v1/libs/TinyDragger.cjs +1 -1
- package/dist/v1/libs/TinyDragger.mjs +1 -1
- package/dist/v1/libs/TinyHtml.cjs +292 -103
- package/dist/v1/libs/TinyHtml.d.mts +142 -39
- package/dist/v1/libs/TinyHtml.mjs +266 -94
- package/dist/v1/libs/TinyIframeEvents.cjs +2 -1
- package/dist/v1/libs/TinyNewWinEvents.cjs +4 -2
- package/docs/v1/libs/TinyHtml.md +128 -6
- package/package.json +1 -1
- package/dist/v1/ColorSafeStringify.js +0 -235
- package/dist/v1/TinyAfterScrollWatcher.js +0 -219
- package/dist/v1/TinyBasicsEs.js +0 -9334
- package/dist/v1/TinyClipboard.js +0 -459
- package/dist/v1/TinyColorConverter.js +0 -617
- package/dist/v1/TinyDomReadyManager.js +0 -213
- package/dist/v1/TinyDragDropDetector.js +0 -307
- package/dist/v1/TinyDragger.js +0 -6569
- package/dist/v1/TinyEssentials.js +0 -20792
- package/dist/v1/TinyEvents.js +0 -402
- package/dist/v1/TinyHtml.js +0 -5545
- package/dist/v1/TinyIframeEvents.js +0 -854
- package/dist/v1/TinyLevelUp.js +0 -291
- package/dist/v1/TinyLocalStorage.js +0 -1440
- package/dist/v1/TinyNewWinEvents.js +0 -888
- package/dist/v1/TinyNotifications.js +0 -408
- package/dist/v1/TinyNotifyCenter.js +0 -493
- package/dist/v1/TinyPromiseQueue.js +0 -299
- package/dist/v1/TinyRateLimiter.js +0 -611
- package/dist/v1/TinySmartScroller.js +0 -7039
- package/dist/v1/TinyTextRangeEditor.js +0 -497
- package/dist/v1/TinyTimeout.js +0 -233
- package/dist/v1/TinyToastNotify.js +0 -441
- package/dist/v1/TinyUploadClicker.js +0 -14353
- package/dist/v1/UltraRandomMsgGen.js +0 -995
|
@@ -240,11 +240,39 @@ class TinyHtml {
|
|
|
240
240
|
|
|
241
241
|
static Utils = { ...collision };
|
|
242
242
|
|
|
243
|
+
/**
|
|
244
|
+
* Creates a new TinyHtml element from a tag name and optional attributes.
|
|
245
|
+
*
|
|
246
|
+
* You can alias this method for convenience:
|
|
247
|
+
* ```js
|
|
248
|
+
* const createElement = TinyHtml.createFrom;
|
|
249
|
+
* const myDiv = createElement('div', { class: 'box' });
|
|
250
|
+
* ```
|
|
251
|
+
*
|
|
252
|
+
* @param {string} tagName - The HTML tag name (e.g., 'div', 'span', 'button').
|
|
253
|
+
* @param {Record<string, string|null>} [attrs] - Optional key-value pairs representing HTML attributes.
|
|
254
|
+
* If the value is `null`, the attribute will still be set with an empty value.
|
|
255
|
+
* @returns {TinyHtml} - A new instance of TinyHtml representing the created element.
|
|
256
|
+
* @throws {TypeError} - If `tagName` is not a string, or `attrs` is not a plain object when defined.
|
|
257
|
+
*/
|
|
258
|
+
static createFrom(tagName, attrs) {
|
|
259
|
+
if (typeof tagName !== 'string') throw new TypeError('The "tagName" must be a string.');
|
|
260
|
+
if (typeof attrs !== 'undefined' && typeof attrs !== 'object')
|
|
261
|
+
throw new TypeError('The "attrs" must be a object.');
|
|
262
|
+
const elem = TinyHtml.createElement(tagName);
|
|
263
|
+
if (typeof attrs === 'object') {
|
|
264
|
+
for (const attrName in attrs) {
|
|
265
|
+
elem.setAttr(attrName, attrs[attrName]);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
return elem;
|
|
269
|
+
}
|
|
270
|
+
|
|
243
271
|
/**
|
|
244
272
|
* Creates a new DOM element with the specified tag name and options, then wraps it in a TinyHtml instance.
|
|
245
273
|
*
|
|
246
274
|
* @param {string} tagName - The tag name of the element to create (e.g., 'div', 'span').
|
|
247
|
-
* @param {ElementCreationOptions} ops - Optional settings for creating the element.
|
|
275
|
+
* @param {ElementCreationOptions} [ops] - Optional settings for creating the element.
|
|
248
276
|
* @returns {TinyHtml} A TinyHtml instance wrapping the newly created DOM element.
|
|
249
277
|
* @throws {TypeError} If tagName is not a string or ops is not an object.
|
|
250
278
|
*/
|
|
@@ -290,7 +318,8 @@ class TinyHtml {
|
|
|
290
318
|
}
|
|
291
319
|
|
|
292
320
|
template.innerHTML = htmlString;
|
|
293
|
-
if (!(template.content.firstChild instanceof Element))
|
|
321
|
+
if (!(template.content.firstChild instanceof Element))
|
|
322
|
+
throw new Error('The HTML string must contain a valid HTML element.');
|
|
294
323
|
return new TinyHtml(template.content.firstChild);
|
|
295
324
|
}
|
|
296
325
|
|
|
@@ -322,18 +351,17 @@ class TinyHtml {
|
|
|
322
351
|
*
|
|
323
352
|
* @param {string} selector - A valid CSS selector string.
|
|
324
353
|
* @param {Document|Element} elem - Target element.
|
|
325
|
-
* @returns {TinyHtml
|
|
354
|
+
* @returns {TinyHtml} An array of TinyHtml instances wrapping the matched elements.
|
|
326
355
|
*/
|
|
327
356
|
static queryAll(selector, elem = document) {
|
|
328
|
-
|
|
329
|
-
return TinyHtml.toTinyElm([...newEls]);
|
|
357
|
+
return new TinyHtml(elem.querySelectorAll(selector));
|
|
330
358
|
}
|
|
331
359
|
|
|
332
360
|
/**
|
|
333
361
|
* Queries the element for all elements matching the CSS selector and wraps them in TinyHtml instances.
|
|
334
362
|
*
|
|
335
363
|
* @param {string} selector - A valid CSS selector string.
|
|
336
|
-
* @returns {TinyHtml
|
|
364
|
+
* @returns {TinyHtml} An array of TinyHtml instances wrapping the matched elements.
|
|
337
365
|
*/
|
|
338
366
|
querySelectorAll(selector) {
|
|
339
367
|
return TinyHtml.queryAll(selector, TinyHtml._preElem(this, 'queryAll'));
|
|
@@ -356,18 +384,17 @@ class TinyHtml {
|
|
|
356
384
|
*
|
|
357
385
|
* @param {string} selector - The class name to search for.
|
|
358
386
|
* @param {Document|Element} elem - Target element.
|
|
359
|
-
* @returns {TinyHtml
|
|
387
|
+
* @returns {TinyHtml} An array of TinyHtml instances wrapping the found elements.
|
|
360
388
|
*/
|
|
361
389
|
static getByClassName(selector, elem = document) {
|
|
362
|
-
|
|
363
|
-
return TinyHtml.toTinyElm([...newEls]);
|
|
390
|
+
return new TinyHtml(elem.getElementsByClassName(selector));
|
|
364
391
|
}
|
|
365
392
|
|
|
366
393
|
/**
|
|
367
394
|
* Retrieves all elements with the specified class name and wraps them in TinyHtml instances.
|
|
368
395
|
*
|
|
369
396
|
* @param {string} selector - The class name to search for.
|
|
370
|
-
* @returns {TinyHtml
|
|
397
|
+
* @returns {TinyHtml} An array of TinyHtml instances wrapping the found elements.
|
|
371
398
|
*/
|
|
372
399
|
getElementsByClassName(selector) {
|
|
373
400
|
return TinyHtml.getByClassName(selector, TinyHtml._preElem(this, 'getByClassName'));
|
|
@@ -377,11 +404,10 @@ class TinyHtml {
|
|
|
377
404
|
* Retrieves all elements with the specified name attribute and wraps them in TinyHtml instances.
|
|
378
405
|
*
|
|
379
406
|
* @param {string} selector - The name attribute to search for.
|
|
380
|
-
* @returns {TinyHtml
|
|
407
|
+
* @returns {TinyHtml} An array of TinyHtml instances wrapping the found elements.
|
|
381
408
|
*/
|
|
382
409
|
static getByName(selector) {
|
|
383
|
-
|
|
384
|
-
return TinyHtml.toTinyElm([...newEls]);
|
|
410
|
+
return new TinyHtml(document.getElementsByName(selector));
|
|
385
411
|
}
|
|
386
412
|
|
|
387
413
|
/**
|
|
@@ -391,11 +417,10 @@ class TinyHtml {
|
|
|
391
417
|
* @param {string} localName - The local name (tag) of the elements to search for.
|
|
392
418
|
* @param {string|null} [namespaceURI='http://www.w3.org/1999/xhtml'] - The namespace URI to search within.
|
|
393
419
|
* @param {Document|Element} elem - Target element.
|
|
394
|
-
* @returns {TinyHtml
|
|
420
|
+
* @returns {TinyHtml} An array of TinyHtml instances wrapping the found elements.
|
|
395
421
|
*/
|
|
396
422
|
static getByTagNameNS(localName, namespaceURI = 'http://www.w3.org/1999/xhtml', elem = document) {
|
|
397
|
-
|
|
398
|
-
return TinyHtml.toTinyElm([...newEls]);
|
|
423
|
+
return new TinyHtml(elem.getElementsByTagNameNS(namespaceURI, localName));
|
|
399
424
|
}
|
|
400
425
|
|
|
401
426
|
/**
|
|
@@ -404,7 +429,7 @@ class TinyHtml {
|
|
|
404
429
|
*
|
|
405
430
|
* @param {string} localName - The local name (tag) of the elements to search for.
|
|
406
431
|
* @param {string|null} [namespaceURI='http://www.w3.org/1999/xhtml'] - The namespace URI to search within.
|
|
407
|
-
* @returns {TinyHtml
|
|
432
|
+
* @returns {TinyHtml} An array of TinyHtml instances wrapping the found elements.
|
|
408
433
|
*/
|
|
409
434
|
getElementsByTagNameNS(localName, namespaceURI = 'http://www.w3.org/1999/xhtml') {
|
|
410
435
|
return TinyHtml.getByTagNameNS(
|
|
@@ -419,85 +444,156 @@ class TinyHtml {
|
|
|
419
444
|
/**
|
|
420
445
|
* Returns the current target held by this instance.
|
|
421
446
|
*
|
|
447
|
+
* @param {number} index - The index of the element to retrieve.
|
|
422
448
|
* @returns {ConstructorElValues} - The instance's target element.
|
|
423
449
|
*/
|
|
424
|
-
get() {
|
|
425
|
-
|
|
450
|
+
get(index) {
|
|
451
|
+
if (typeof index !== 'number') throw new TypeError('The index must be a number.');
|
|
452
|
+
if (!this.#el[index]) throw new Error(`No element found at index ${index}.`);
|
|
453
|
+
return this.#el[index];
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
/**
|
|
457
|
+
* Extracts a single DOM element from the internal list at the specified index.
|
|
458
|
+
*
|
|
459
|
+
* @param {number} index - The index of the element to extract.
|
|
460
|
+
* @returns {TinyHtml} A new TinyHtml instance wrapping the extracted element.
|
|
461
|
+
*/
|
|
462
|
+
extract(index) {
|
|
463
|
+
if (typeof index !== 'number') throw new TypeError('The index must be a number.');
|
|
464
|
+
if (!this.#el[index]) throw new Error(`Cannot extract: no element exists at index ${index}.`);
|
|
465
|
+
return new TinyHtml(this.#el[index]);
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
/**
|
|
469
|
+
* Checks whether the element exists at the given index.
|
|
470
|
+
*
|
|
471
|
+
* @param {number} index - The index to check.
|
|
472
|
+
* @returns {boolean} - True if the element exists; otherwise, false.
|
|
473
|
+
*/
|
|
474
|
+
exists(index) {
|
|
475
|
+
if (typeof index !== 'number') throw new TypeError('The index must be a number.');
|
|
476
|
+
if (!this.#el[index]) return false;
|
|
477
|
+
return true;
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
/**
|
|
481
|
+
* Returns the current targets held by this instance.
|
|
482
|
+
*
|
|
483
|
+
* @returns {ConstructorElValues[]} - The instance's targets element.
|
|
484
|
+
*/
|
|
485
|
+
getAll() {
|
|
486
|
+
return [...this.#el];
|
|
426
487
|
}
|
|
427
488
|
|
|
428
489
|
/**
|
|
429
490
|
* Returns the current Element held by this instance.
|
|
430
491
|
*
|
|
431
492
|
* @param {string} where - The method name or context calling this.
|
|
493
|
+
* @param {number} index - The index of the element to retrieve.
|
|
432
494
|
* @returns {ConstructorElValues} - The instance's element.
|
|
433
495
|
* @readonly
|
|
434
496
|
*/
|
|
435
|
-
_getElement(where) {
|
|
497
|
+
_getElement(where, index) {
|
|
436
498
|
if (
|
|
437
|
-
!(this.#el instanceof Element) &&
|
|
438
|
-
!(this.#el instanceof Window) &&
|
|
439
|
-
!(this.#el instanceof Document)
|
|
499
|
+
!(this.#el[index] instanceof Element) &&
|
|
500
|
+
!(this.#el[index] instanceof Window) &&
|
|
501
|
+
!(this.#el[index] instanceof Document)
|
|
440
502
|
)
|
|
441
503
|
throw new Error(`[TinyHtml] Invalid Element in ${where}().`);
|
|
442
|
-
return this.#el;
|
|
504
|
+
return this.#el[index];
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
/**
|
|
508
|
+
* Returns the current Elements held by this instance.
|
|
509
|
+
*
|
|
510
|
+
* @param {string} where - The method name or context calling this.
|
|
511
|
+
* @returns {ConstructorElValues[]} - The instance's elements.
|
|
512
|
+
* @readonly
|
|
513
|
+
*/
|
|
514
|
+
_getElements(where) {
|
|
515
|
+
if (
|
|
516
|
+
!this.#el.every(
|
|
517
|
+
(el) => el instanceof Element || el instanceof Window || el instanceof Document,
|
|
518
|
+
)
|
|
519
|
+
)
|
|
520
|
+
throw new Error(`[TinyHtml] Invalid Element in ${where}().`);
|
|
521
|
+
return [...this.#el];
|
|
443
522
|
}
|
|
444
523
|
|
|
445
524
|
//////////////////////////////////////////////////////
|
|
446
525
|
|
|
447
526
|
/**
|
|
448
|
-
*
|
|
449
|
-
*
|
|
450
|
-
* @param {
|
|
451
|
-
* @param {string
|
|
452
|
-
* @
|
|
527
|
+
* Prepares and validates multiple elements against allowed types.
|
|
528
|
+
*
|
|
529
|
+
* @param {TinyElement | EventTarget | null | (TinyElement | EventTarget | null)[]} elems - The input elements to validate.
|
|
530
|
+
* @param {string} where - The method name or context calling this.
|
|
531
|
+
* @param {any[]} TheTinyElements - The list of allowed constructors (e.g., Element, Document).
|
|
532
|
+
* @param {string[]} elemName - The list of expected element names for error reporting.
|
|
533
|
+
* @returns {any[]} - A flat array of validated elements.
|
|
534
|
+
* @throws {Error} - If any element is not an instance of one of the allowed types.
|
|
453
535
|
* @readonly
|
|
454
536
|
*/
|
|
455
537
|
static _preElemsTemplate(elems, where, TheTinyElements, elemName) {
|
|
456
538
|
/** @param {(TinyElement|EventTarget|null)[]} item */
|
|
457
|
-
const checkElement = (item) =>
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
539
|
+
const checkElement = (item) => {
|
|
540
|
+
/** @type {any[]} */
|
|
541
|
+
const results = [];
|
|
542
|
+
item.map((elem) =>
|
|
543
|
+
(elem instanceof TinyHtml ? elem._getElements(where) : [elem]).map((result) => {
|
|
544
|
+
let allowed = false;
|
|
545
|
+
for (const TheTinyElement of TheTinyElements) {
|
|
546
|
+
if (result instanceof TheTinyElement) {
|
|
547
|
+
allowed = true;
|
|
548
|
+
break;
|
|
549
|
+
}
|
|
465
550
|
}
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
);
|
|
471
|
-
|
|
472
|
-
|
|
551
|
+
if (!allowed)
|
|
552
|
+
throw new Error(
|
|
553
|
+
`[TinyHtml] Invalid element of the list "${elemName.join(',')}" in ${where}().`,
|
|
554
|
+
);
|
|
555
|
+
results.push(result);
|
|
556
|
+
return result;
|
|
557
|
+
}),
|
|
558
|
+
);
|
|
559
|
+
return results;
|
|
560
|
+
};
|
|
473
561
|
if (!Array.isArray(elems)) return checkElement([elems]);
|
|
474
562
|
return checkElement(elems);
|
|
475
563
|
}
|
|
476
564
|
|
|
477
565
|
/**
|
|
478
|
-
*
|
|
479
|
-
*
|
|
480
|
-
* @param {
|
|
481
|
-
* @param {string
|
|
482
|
-
* @param {
|
|
483
|
-
* @
|
|
566
|
+
* Prepares and validates a single element against allowed types.
|
|
567
|
+
*
|
|
568
|
+
* @param {TinyElement | EventTarget | null | (TinyElement | EventTarget | null)[]} elems - The input element or list to validate.
|
|
569
|
+
* @param {string} where - The method name or context calling this.
|
|
570
|
+
* @param {any[]} TheTinyElements - The list of allowed constructors (e.g., Element, Document).
|
|
571
|
+
* @param {string[]} elemName - The list of expected element names for error reporting.
|
|
572
|
+
* @param {boolean} [canNull=false] - Whether `null` is allowed as a valid value.
|
|
573
|
+
* @returns {any} - The validated element or `null` if allowed.
|
|
574
|
+
* @throws {Error} - If the element is not valid or if multiple elements are provided.
|
|
484
575
|
* @readonly
|
|
485
576
|
*/
|
|
486
577
|
static _preElemTemplate(elems, where, TheTinyElements, elemName, canNull = false) {
|
|
487
578
|
/** @param {(TinyElement|EventTarget|null)[]} item */
|
|
488
579
|
const checkElement = (item) => {
|
|
489
580
|
const elem = item[0];
|
|
490
|
-
|
|
581
|
+
const result = elem instanceof TinyHtml ? elem._getElements(where) : [elem];
|
|
582
|
+
if (result.length > 1)
|
|
583
|
+
throw new Error(
|
|
584
|
+
`[TinyHtml] Invalid element amount in ${where}() (Received ${result.length}/1).`,
|
|
585
|
+
);
|
|
586
|
+
|
|
491
587
|
let allowed = false;
|
|
492
588
|
for (const TheTinyElement of TheTinyElements) {
|
|
493
|
-
if (result instanceof TheTinyElement) {
|
|
589
|
+
if (result[0] instanceof TheTinyElement) {
|
|
494
590
|
allowed = true;
|
|
495
591
|
break;
|
|
496
592
|
}
|
|
497
593
|
}
|
|
498
594
|
|
|
499
|
-
if (canNull && (result === null || typeof result === 'undefined')) {
|
|
500
|
-
result = null;
|
|
595
|
+
if (canNull && (result[0] === null || typeof result[0] === 'undefined')) {
|
|
596
|
+
result[0] = null;
|
|
501
597
|
allowed = true;
|
|
502
598
|
}
|
|
503
599
|
|
|
@@ -505,7 +601,7 @@ class TinyHtml {
|
|
|
505
601
|
throw new Error(
|
|
506
602
|
`[TinyHtml] Invalid element of the list "${elemName.join(',')}" in ${where}().`,
|
|
507
603
|
);
|
|
508
|
-
return result;
|
|
604
|
+
return result[0];
|
|
509
605
|
};
|
|
510
606
|
if (!Array.isArray(elems)) return checkElement([elems]);
|
|
511
607
|
if (elems.length > 1)
|
|
@@ -798,13 +894,16 @@ class TinyHtml {
|
|
|
798
894
|
*/
|
|
799
895
|
static fromTinyElm(elems) {
|
|
800
896
|
/** @param {TinyElement[]} item */
|
|
801
|
-
const checkElement = (item) =>
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
)
|
|
897
|
+
const checkElement = (item) => {
|
|
898
|
+
/** @type {Element[]} */
|
|
899
|
+
const result = [];
|
|
900
|
+
item.map((elem) =>
|
|
901
|
+
/** @type {Element[]} */ (
|
|
902
|
+
elem instanceof TinyHtml ? elem._getElements('fromTinyElm') : [elem]
|
|
903
|
+
).map((elem) => result.push(elem)),
|
|
807
904
|
);
|
|
905
|
+
return result;
|
|
906
|
+
};
|
|
808
907
|
if (!Array.isArray(elems)) return checkElement([elems]);
|
|
809
908
|
return checkElement(elems);
|
|
810
909
|
}
|
|
@@ -1648,7 +1747,8 @@ class TinyHtml {
|
|
|
1648
1747
|
const elem = TinyHtml._preNodeElem(el, 'insertBefore');
|
|
1649
1748
|
const targ = TinyHtml._preNodeElem(target, 'insertBefore');
|
|
1650
1749
|
const childNode = TinyHtml._preNodeElemWithNull(child, 'insertBefore');
|
|
1651
|
-
if (!targ.parentNode)
|
|
1750
|
+
if (!targ.parentNode)
|
|
1751
|
+
throw new Error('The target element has no parent node to insert before.');
|
|
1652
1752
|
targ.parentNode.insertBefore(elem, childNode || targ);
|
|
1653
1753
|
return el;
|
|
1654
1754
|
}
|
|
@@ -1676,7 +1776,7 @@ class TinyHtml {
|
|
|
1676
1776
|
const elem = TinyHtml._preNodeElem(el, 'insertAfter');
|
|
1677
1777
|
const targ = TinyHtml._preNodeElem(target, 'insertBefore');
|
|
1678
1778
|
const childNode = TinyHtml._preNodeElemWithNull(child, 'insertBefore');
|
|
1679
|
-
if (!targ.parentNode) throw new Error('');
|
|
1779
|
+
if (!targ.parentNode) throw new Error('The target element has no parent node to insert after.');
|
|
1680
1780
|
targ.parentNode.insertBefore(elem, childNode || targ.nextSibling);
|
|
1681
1781
|
return el;
|
|
1682
1782
|
}
|
|
@@ -1728,28 +1828,48 @@ class TinyHtml {
|
|
|
1728
1828
|
|
|
1729
1829
|
/**
|
|
1730
1830
|
* The target HTML element for instance-level operations.
|
|
1731
|
-
* @type {ConstructorElValues}
|
|
1831
|
+
* @type {ConstructorElValues[]}
|
|
1732
1832
|
*/
|
|
1733
1833
|
#el;
|
|
1734
1834
|
|
|
1735
1835
|
/**
|
|
1736
1836
|
* Creates an instance of TinyHtml for a specific Element.
|
|
1737
1837
|
* Useful when you want to operate repeatedly on the same element using instance methods.
|
|
1738
|
-
* @param {ConstructorElValues} el - The element to wrap and manipulate.
|
|
1838
|
+
* @param {ConstructorElValues|ConstructorElValues[]|NodeListOf<Element>|HTMLCollectionOf<Element>|NodeListOf<HTMLElement>} el - The element to wrap and manipulate.
|
|
1739
1839
|
*/
|
|
1740
1840
|
constructor(el) {
|
|
1741
1841
|
if (el instanceof TinyHtml)
|
|
1742
1842
|
throw new Error(
|
|
1743
1843
|
`[TinyHtml] You are trying to put a TinyHtml inside another TinyHtml in constructor.`,
|
|
1744
1844
|
);
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1845
|
+
|
|
1846
|
+
/** @param {any[]} els */
|
|
1847
|
+
const elCheck = (els) => {
|
|
1848
|
+
if (
|
|
1849
|
+
!els.every(
|
|
1850
|
+
(el) =>
|
|
1851
|
+
el instanceof Element ||
|
|
1852
|
+
el instanceof Window ||
|
|
1853
|
+
el instanceof Document ||
|
|
1854
|
+
el instanceof Text,
|
|
1855
|
+
)
|
|
1856
|
+
)
|
|
1857
|
+
throw new Error(`[TinyHtml] Invalid Target in constructor.`);
|
|
1858
|
+
};
|
|
1859
|
+
|
|
1860
|
+
if (Array.isArray(el)) {
|
|
1861
|
+
elCheck(el);
|
|
1862
|
+
this.#el = el;
|
|
1863
|
+
} else if (el instanceof NodeList || el instanceof HTMLCollection) {
|
|
1864
|
+
const els = [...el];
|
|
1865
|
+
elCheck(els);
|
|
1866
|
+
this.#el = els;
|
|
1867
|
+
} else {
|
|
1868
|
+
const els = [el];
|
|
1869
|
+
elCheck(els);
|
|
1870
|
+
// @ts-ignore
|
|
1871
|
+
this.#el = els;
|
|
1872
|
+
}
|
|
1753
1873
|
}
|
|
1754
1874
|
|
|
1755
1875
|
/**
|
|
@@ -2153,7 +2273,13 @@ class TinyHtml {
|
|
|
2153
2273
|
msTransition: '-ms-transition',
|
|
2154
2274
|
};
|
|
2155
2275
|
|
|
2156
|
-
/**
|
|
2276
|
+
/**
|
|
2277
|
+
* Public proxy to manage camelCase ➝ kebab-case CSS property aliasing.
|
|
2278
|
+
*
|
|
2279
|
+
* Modifying this object ensures that the reverse mapping in `cssPropRevAliases` is updated accordingly.
|
|
2280
|
+
*
|
|
2281
|
+
* @type {Record<string | symbol, string>}
|
|
2282
|
+
*/
|
|
2157
2283
|
static cssPropAliases = new Proxy(TinyHtml.#cssPropAliases, {
|
|
2158
2284
|
set(target, camelCaseKey, kebabValue) {
|
|
2159
2285
|
target[camelCaseKey] = kebabValue;
|
|
@@ -2163,7 +2289,13 @@ class TinyHtml {
|
|
|
2163
2289
|
},
|
|
2164
2290
|
});
|
|
2165
2291
|
|
|
2166
|
-
/**
|
|
2292
|
+
/**
|
|
2293
|
+
* Reverse map of `cssPropAliases`, mapping kebab-case back to camelCase CSS property names.
|
|
2294
|
+
*
|
|
2295
|
+
* This enables consistent bidirectional lookups of style properties.
|
|
2296
|
+
*
|
|
2297
|
+
* @type {Record<string | symbol, string>}
|
|
2298
|
+
*/
|
|
2167
2299
|
static cssPropRevAliases = Object.fromEntries(
|
|
2168
2300
|
Object.entries(TinyHtml.#cssPropAliases).map(([camel, kebab]) => [kebab, camel]),
|
|
2169
2301
|
);
|
|
@@ -3804,7 +3936,7 @@ class TinyHtml {
|
|
|
3804
3936
|
static _getValByType(elem, type, where) {
|
|
3805
3937
|
if (typeof type !== 'string') throw new TypeError('The "type" must be a string.');
|
|
3806
3938
|
if (typeof where !== 'string') throw new TypeError('The "where" must be a string.');
|
|
3807
|
-
if (!(elem instanceof HTMLInputElement))
|
|
3939
|
+
if (!(elem instanceof HTMLInputElement) && !(elem instanceof HTMLTextAreaElement))
|
|
3808
3940
|
throw new Error(`Provided element is not an HTMLInputElement in ${where}().`);
|
|
3809
3941
|
if (typeof TinyHtml._valTypes[type] !== 'function')
|
|
3810
3942
|
throw new Error(`No handler found for type "${type}" in ${where}().`);
|
|
@@ -4345,14 +4477,77 @@ class TinyHtml {
|
|
|
4345
4477
|
///////////////////////////////////////////////////////////////
|
|
4346
4478
|
|
|
4347
4479
|
/**
|
|
4348
|
-
*
|
|
4349
|
-
*
|
|
4480
|
+
* Internal property name normalization map (similar to jQuery's `propFix`).
|
|
4481
|
+
* Maps attribute-like names to their JavaScript DOM property equivalents.
|
|
4482
|
+
*
|
|
4483
|
+
* Example: `'for'` ➝ `'htmlFor'`, `'class'` ➝ `'className'`.
|
|
4484
|
+
*
|
|
4485
|
+
* ⚠️ Do not modify this object directly. Use `TinyHtml.propFix` to ensure reverse mapping (`attrFix`) remains in sync.
|
|
4486
|
+
*
|
|
4487
|
+
* @type {Record<string | symbol, string>}
|
|
4350
4488
|
*/
|
|
4351
|
-
static
|
|
4489
|
+
static #propFix = {
|
|
4352
4490
|
for: 'htmlFor',
|
|
4353
4491
|
class: 'className',
|
|
4354
4492
|
};
|
|
4355
4493
|
|
|
4494
|
+
/**
|
|
4495
|
+
* Public proxy for normalized DOM property names.
|
|
4496
|
+
*
|
|
4497
|
+
* Setting a new entry here will also automatically update the reverse map in `TinyHtml.attrFix`.
|
|
4498
|
+
*
|
|
4499
|
+
* @type {Record<string | symbol, string>}
|
|
4500
|
+
*/
|
|
4501
|
+
static propFix = new Proxy(TinyHtml.#propFix, {
|
|
4502
|
+
set(target, val1, val2) {
|
|
4503
|
+
target[val1] = val2;
|
|
4504
|
+
// @ts-ignore
|
|
4505
|
+
TinyHtml.attrFix[val2] = val1;
|
|
4506
|
+
return true;
|
|
4507
|
+
},
|
|
4508
|
+
});
|
|
4509
|
+
|
|
4510
|
+
/**
|
|
4511
|
+
* Reverse map of `propFix`, mapping property names back to their attribute equivalents.
|
|
4512
|
+
*
|
|
4513
|
+
* Used when converting DOM property names into HTML attribute names.
|
|
4514
|
+
*
|
|
4515
|
+
* @type {Record<string | symbol, string>}
|
|
4516
|
+
*/
|
|
4517
|
+
static attrFix = Object.fromEntries(
|
|
4518
|
+
Object.entries(TinyHtml.#propFix).map(([val1, val2]) => [val2, val1]),
|
|
4519
|
+
);
|
|
4520
|
+
|
|
4521
|
+
/**
|
|
4522
|
+
* Normalizes an attribute name to its corresponding DOM property name.
|
|
4523
|
+
*
|
|
4524
|
+
* Example: `'class'` ➝ `'className'`, `'for'` ➝ `'htmlFor'`.
|
|
4525
|
+
* If the name is not mapped, it returns the original name.
|
|
4526
|
+
*
|
|
4527
|
+
* @param {string} name - The attribute name to normalize.
|
|
4528
|
+
* @returns {string} - The corresponding property name.
|
|
4529
|
+
*/
|
|
4530
|
+
static getPropName(name) {
|
|
4531
|
+
// @ts-ignore
|
|
4532
|
+
const propName = typeof TinyHtml.propFix[name] === 'string' ? TinyHtml.propFix[name] : name;
|
|
4533
|
+
return propName;
|
|
4534
|
+
}
|
|
4535
|
+
|
|
4536
|
+
/**
|
|
4537
|
+
* Converts a DOM property name back to its corresponding attribute name.
|
|
4538
|
+
*
|
|
4539
|
+
* Example: `'className'` ➝ `'class'`, `'htmlFor'` ➝ `'for'`.
|
|
4540
|
+
* If the name is not mapped, it returns the original name.
|
|
4541
|
+
*
|
|
4542
|
+
* @param {string} name - The property name to convert.
|
|
4543
|
+
* @returns {string} - The corresponding attribute name.
|
|
4544
|
+
*/
|
|
4545
|
+
static getAttrName(name) {
|
|
4546
|
+
// @ts-ignore
|
|
4547
|
+
const propName = typeof TinyHtml.attrFix[name] === 'string' ? TinyHtml.attrFix[name] : name;
|
|
4548
|
+
return propName;
|
|
4549
|
+
}
|
|
4550
|
+
|
|
4356
4551
|
/**
|
|
4357
4552
|
* Get an attribute on an element.
|
|
4358
4553
|
* @param {TinyElement} el
|
|
@@ -4362,7 +4557,7 @@ class TinyHtml {
|
|
|
4362
4557
|
static attr(el, name) {
|
|
4363
4558
|
if (typeof name !== 'string') throw new TypeError('The "name" must be a string.');
|
|
4364
4559
|
const elem = TinyHtml._preElem(el, 'attr');
|
|
4365
|
-
return elem.getAttribute(name);
|
|
4560
|
+
return elem.getAttribute(TinyHtml.getAttrName(name));
|
|
4366
4561
|
}
|
|
4367
4562
|
|
|
4368
4563
|
/**
|
|
@@ -4386,8 +4581,8 @@ class TinyHtml {
|
|
|
4386
4581
|
if (value !== null && typeof value !== 'string')
|
|
4387
4582
|
throw new TypeError('The "value" must be a string.');
|
|
4388
4583
|
TinyHtml._preElems(el, 'setAttr').forEach((elem) => {
|
|
4389
|
-
if (value === null) elem.removeAttribute(name);
|
|
4390
|
-
else elem.setAttribute(name, value);
|
|
4584
|
+
if (value === null) elem.removeAttribute(TinyHtml.getAttrName(name));
|
|
4585
|
+
else elem.setAttribute(TinyHtml.getAttrName(name), value);
|
|
4391
4586
|
});
|
|
4392
4587
|
return el;
|
|
4393
4588
|
}
|
|
@@ -4410,7 +4605,9 @@ class TinyHtml {
|
|
|
4410
4605
|
*/
|
|
4411
4606
|
static removeAttr(el, name) {
|
|
4412
4607
|
if (typeof name !== 'string') throw new TypeError('The "name" must be a string.');
|
|
4413
|
-
TinyHtml._preElems(el, 'removeAttr').forEach((elem) =>
|
|
4608
|
+
TinyHtml._preElems(el, 'removeAttr').forEach((elem) =>
|
|
4609
|
+
elem.removeAttribute(TinyHtml.getAttrName(name)),
|
|
4610
|
+
);
|
|
4414
4611
|
return el;
|
|
4415
4612
|
}
|
|
4416
4613
|
|
|
@@ -4432,7 +4629,7 @@ class TinyHtml {
|
|
|
4432
4629
|
static hasAttr(el, name) {
|
|
4433
4630
|
if (typeof name !== 'string') throw new TypeError('The "name" must be a string.');
|
|
4434
4631
|
const elem = TinyHtml._preElem(el, 'hasAttr');
|
|
4435
|
-
return elem.hasAttribute(name);
|
|
4632
|
+
return elem.hasAttribute(TinyHtml.getAttrName(name));
|
|
4436
4633
|
}
|
|
4437
4634
|
|
|
4438
4635
|
/**
|
|
@@ -4454,9 +4651,7 @@ class TinyHtml {
|
|
|
4454
4651
|
if (typeof name !== 'string') throw new TypeError('The "name" must be a string.');
|
|
4455
4652
|
const elem = TinyHtml._preElem(el, 'hasProp');
|
|
4456
4653
|
// @ts-ignore
|
|
4457
|
-
|
|
4458
|
-
// @ts-ignore
|
|
4459
|
-
return !!elem[propName];
|
|
4654
|
+
return !!elem[TinyHtml.getPropName(name)];
|
|
4460
4655
|
}
|
|
4461
4656
|
|
|
4462
4657
|
/**
|
|
@@ -4478,9 +4673,7 @@ class TinyHtml {
|
|
|
4478
4673
|
if (typeof name !== 'string') throw new TypeError('The "name" must be a string.');
|
|
4479
4674
|
TinyHtml._preElems(el, 'addProp').forEach((elem) => {
|
|
4480
4675
|
// @ts-ignore
|
|
4481
|
-
|
|
4482
|
-
// @ts-ignore
|
|
4483
|
-
elem[name] = true;
|
|
4676
|
+
elem[TinyHtml.getPropName(name)] = true;
|
|
4484
4677
|
});
|
|
4485
4678
|
return el;
|
|
4486
4679
|
}
|
|
@@ -4504,9 +4697,7 @@ class TinyHtml {
|
|
|
4504
4697
|
if (typeof name !== 'string') throw new TypeError('The "name" must be a string.');
|
|
4505
4698
|
TinyHtml._preElems(el, 'removeProp').forEach((elem) => {
|
|
4506
4699
|
// @ts-ignore
|
|
4507
|
-
|
|
4508
|
-
// @ts-ignore
|
|
4509
|
-
elem[name] = false;
|
|
4700
|
+
elem[TinyHtml.getPropName(name)] = false;
|
|
4510
4701
|
});
|
|
4511
4702
|
return el;
|
|
4512
4703
|
}
|
|
@@ -4532,9 +4723,7 @@ class TinyHtml {
|
|
|
4532
4723
|
throw new TypeError('The "force" must be a boolean.');
|
|
4533
4724
|
TinyHtml._preElems(el, 'toggleProp').forEach((elem) => {
|
|
4534
4725
|
// @ts-ignore
|
|
4535
|
-
const
|
|
4536
|
-
// @ts-ignore
|
|
4537
|
-
const shouldEnable = force === undefined ? !elem[propName] : force;
|
|
4726
|
+
const shouldEnable = force === undefined ? !elem[TinyHtml.getPropName(name)] : force;
|
|
4538
4727
|
// @ts-ignore
|
|
4539
4728
|
if (shouldEnable) TinyHtml.addProp(elem, name);
|
|
4540
4729
|
else TinyHtml.removeProp(elem, name);
|
|
@@ -4637,14 +4826,14 @@ class TinyHtml {
|
|
|
4637
4826
|
}
|
|
4638
4827
|
|
|
4639
4828
|
if (typeof extraRect !== 'object' || extraRect === null || Array.isArray(extraRect))
|
|
4640
|
-
throw new Error('');
|
|
4829
|
+
throw new Error('extraRect must be a non-null object.');
|
|
4641
4830
|
const { height = 0, width = 0, top = 0, bottom = 0, left = 0, right = 0 } = extraRect;
|
|
4642
|
-
if (typeof height !== 'number') throw new Error('');
|
|
4643
|
-
if (typeof width !== 'number') throw new Error('');
|
|
4644
|
-
if (typeof top !== 'number') throw new Error('');
|
|
4645
|
-
if (typeof bottom !== 'number') throw new Error('');
|
|
4646
|
-
if (typeof left !== 'number') throw new Error('');
|
|
4647
|
-
if (typeof right !== 'number') throw new Error('');
|
|
4831
|
+
if (typeof height !== 'number') throw new Error('extraRect.height must be a number.');
|
|
4832
|
+
if (typeof width !== 'number') throw new Error('extraRect.width must be a number.');
|
|
4833
|
+
if (typeof top !== 'number') throw new Error('extraRect.top must be a number.');
|
|
4834
|
+
if (typeof bottom !== 'number') throw new Error('extraRect.bottom must be a number.');
|
|
4835
|
+
if (typeof left !== 'number') throw new Error('extraRect.left must be a number.');
|
|
4836
|
+
if (typeof right !== 'number') throw new Error('extraRect.right must be a number.');
|
|
4648
4837
|
|
|
4649
4838
|
// @ts-ignore
|
|
4650
4839
|
result.height += height;
|