feat(ipub): base elements on IPUBElement

This makes the random hex ID logic shared between all elements
This commit is contained in:
Guz
2025-10-17 17:13:57 -03:00
parent 11456db9c4
commit 185ca863fe

View File

@@ -1,19 +1,46 @@
"use strict";
/**
* @param {string} str
* @returns {string}
*/
function hashString(str) {
return Array.from(str).reduce(
(s, c) => (Math.imul(31, s) + c.charCodeAt(0)) | 0,
0,
);
class IPUBElement extends HTMLElement {
static observedAttributes = ["id"];
connectedCallback() {
this.ensureID();
}
attributeChangedCallback(_name, _oldValue, _newValue) {
this.ensureID();
}
ensureID() {
if (this.id) {
return;
}
// INFO: Hash algorithm by Joe Freeman & Cristian Sanchez at StackOverflow:
// https://stackoverflow.com/a/16348977
// https://stackoverflow.com/a/3426956
//
// Licensed under CC BY-SA 3.0 (https://creativecommons.org/licenses/by-sa/3.0/)
let hash = 0;
this.innerHTML.split("").forEach((char) => {
hash = char.charCodeAt(0) + ((hash << 5) - hash);
});
let id = "";
for (let i = 0; i < 3; i++) {
id += ((hash >> (i * 8)) & 0xff).toString(16).padStart(2, "0");
}
this.id = id;
}
}
class IPUBBackground extends HTMLElement {
class IPUBBackground extends IPUBElement {
static elementName = "ipub-background";
static observedAttributes = ["sticky", "fade", "id"];
static observedAttributes = ["sticky", "fade"].concat(
super.observedAttributes,
);
/**
* @private
@@ -63,37 +90,23 @@ class IPUBBackground extends HTMLElement {
})();
attributeChangedCallback(name, _oldValue, _newValue) {
console.debug("IPUBBackground: attribute changed", name);
switch (name) {
case "id": {
if (!this.id) {
console.warn(
`IPUBBackground: no ID specified, assigning one based on innerHTML`,
this,
);
this.id = hashString(this.innerHTML);
}
break;
}
case "fade": {
const image = this.querySelector("img");
if (image) {
console.debug(
`IPUBBackground: ipub-background#${this.id} to observer`,
);
super.attributeChangedCallback();
if (this.hasAttribute("fade")) {
IPUBBackground.#observer.observe(image);
} else {
IPUBBackground.#observer.unobserve(image);
}
if (name === "fade") {
const image = this.querySelector("img");
if (image) {
console.debug(`IPUBBackground: ipub-background#${this.id} to observer`);
const perc = getPercentageInView(image);
if (perc > 0) {
this.fade(perc);
}
if (this.hasAttribute("fade")) {
IPUBBackground.#observer.observe(image);
} else {
IPUBBackground.#observer.unobserve(image);
}
const perc = getPercentageInView(image);
if (perc > 0) {
this.fade(perc);
}
break;
}
}
}
@@ -122,11 +135,11 @@ class IPUBBackground extends HTMLElement {
}
}
class IPUBContent extends HTMLElement {
class IPUBContent extends IPUBElement {
static elementName = "ipub-content";
}
class IPUBImage extends HTMLElement {
class IPUBImage extends IPUBElement {
static elementName = "ipub-image";
}