diff --git a/src/content/listing.js b/src/content/listing.js index 2fe94e5..6b4014c 100644 --- a/src/content/listing.js +++ b/src/content/listing.js @@ -1,10 +1,11 @@ import {createMaintenancePopup} from "$lib/components/MaintenancePopup.js"; import {createMediaBoxTools} from "$lib/components/MediaBoxToolsEvents.js"; +import {initializeMediaBox} from "$lib/components/MediaBoxWrapper.js"; document.querySelectorAll('.media-box').forEach(mediaBoxElement => { - mediaBoxElement.appendChild( + initializeMediaBox(mediaBoxElement, [ createMediaBoxTools( createMaintenancePopup() ) - ); + ]); }); diff --git a/src/lib/components/MaintenancePopup.js b/src/lib/components/MaintenancePopup.js index 6dd6818..e2fc070 100644 --- a/src/lib/components/MaintenancePopup.js +++ b/src/lib/components/MaintenancePopup.js @@ -1,6 +1,7 @@ import MaintenanceSettings from "$lib/extension/settings/MaintenanceSettings.js"; import MaintenanceProfile from "$entities/MaintenanceProfile.js"; import {BaseComponent} from "$lib/components/base/BaseComponent.js"; +import {getComponent} from "$lib/components/base/ComponentUtils.js"; export class MaintenancePopup extends BaseComponent { /** @type {HTMLElement} */ @@ -13,7 +14,7 @@ export class MaintenancePopup extends BaseComponent { #activeProfile = null; /** @type {import('$lib/components/MediaBoxToolsEvents.js').MediaBoxTools|null} */ - #parentTools = null; + #mediaBoxTools = null; /** * @protected @@ -34,16 +35,22 @@ export class MaintenancePopup extends BaseComponent { * @protected */ init() { - this.once('tools-init', this.#onToolsContainerInitialized.bind(this)); - MaintenancePopup.#watchActiveProfile(this.#onActiveProfileChanged.bind(this)); - } + const mediaBoxToolsElement = this.container.closest('.media-box-tools'); - /** - * @param {import('$lib/components/MediaBoxToolsEvents.js').MediaBoxTools} toolsInstance - */ - #onToolsContainerInitialized(toolsInstance) { - this.#parentTools = toolsInstance; - this.emit('active-profile-changed', this.#activeProfile); + if (!mediaBoxToolsElement) { + throw new Error('Maintenance popup initialized outside of the media box tools!'); + } + + /** @type {MediaBoxTools|null} */ + const mediaBoxTools = getComponent(mediaBoxToolsElement); + + if (!mediaBoxTools) { + throw new Error('Media box tools component not found!'); + } + + this.#mediaBoxTools = mediaBoxTools; + + MaintenancePopup.#watchActiveProfile(this.#onActiveProfileChanged.bind(this)); } /** @@ -73,6 +80,19 @@ export class MaintenancePopup extends BaseComponent { this.#tagsList[index] = tagElement; this.#tagsListElement.appendChild(tagElement); }); + + if (this.#mediaBoxTools) { + const tagsAndAliases = this.#mediaBoxTools.mediaBox.tagsAndAliases; + + for (let tagElement of this.#tagsList) { + const tagName = tagElement.dataset.name; + const isPresent = tagsAndAliases.has(tagName); + + tagElement.classList.toggle('is-present', isPresent); + tagElement.classList.toggle('is-missing', !isPresent); + tagElement.classList.toggle('is-aliased', isPresent && tagsAndAliases.get(tagName) !== tagName); + } + } } /** @@ -145,7 +165,7 @@ export class MaintenancePopup extends BaseComponent { export function createMaintenancePopup() { const container = document.createElement('div'); - new MaintenancePopup(container).initialize(); + new MaintenancePopup(container); return container; } diff --git a/src/lib/components/MediaBoxToolsEvents.js b/src/lib/components/MediaBoxToolsEvents.js index 31d80a0..5b931ec 100644 --- a/src/lib/components/MediaBoxToolsEvents.js +++ b/src/lib/components/MediaBoxToolsEvents.js @@ -3,10 +3,21 @@ import {getComponent} from "$lib/components/base/ComponentUtils.js"; import {MaintenancePopup} from "$lib/components/MaintenancePopup.js"; export class MediaBoxTools extends BaseComponent { + /** @type {import('MediaBoxWrapper.js').MediaBoxWrapper|null} */ + #mediaBox; + /** @type {MaintenancePopup|null} */ #maintenancePopup = null; init() { + const mediaBoxElement = this.container.closest('.media-box'); + + if (!mediaBoxElement) { + throw new Error('Toolbox element initialized outside of the media box!'); + } + + this.#mediaBox = getComponent(mediaBoxElement); + for (let childElement of this.container.children) { const component = getComponent(childElement); @@ -14,11 +25,13 @@ export class MediaBoxTools extends BaseComponent { continue; } + if (!component.isInitialized) { + component.initialize(); + } + if (!this.#maintenancePopup && component instanceof MaintenancePopup) { this.#maintenancePopup = component; } - - component.emit('tools-init', this); } this.on('active-profile-changed', this.#onActiveProfileChanged.bind(this)); @@ -37,6 +50,13 @@ export class MediaBoxTools extends BaseComponent { get maintenancePopup() { return this.#maintenancePopup; } + + /** + * @return {import('MediaBoxWrapper.js').MediaBoxWrapper|null} + */ + get mediaBox() { + return this.#mediaBox; + } } /** @@ -52,7 +72,7 @@ export function createMediaBoxTools(...childrenElements) { mediaBoxToolsContainer.append(...childrenElements); } - new MediaBoxTools(mediaBoxToolsContainer).initialize(); + new MediaBoxTools(mediaBoxToolsContainer); return mediaBoxToolsContainer; } diff --git a/src/lib/components/MediaBoxWrapper.js b/src/lib/components/MediaBoxWrapper.js new file mode 100644 index 0000000..98e236e --- /dev/null +++ b/src/lib/components/MediaBoxWrapper.js @@ -0,0 +1,70 @@ +import {BaseComponent} from "$lib/components/base/BaseComponent.js"; +import {getComponent} from "$lib/components/base/ComponentUtils.js"; + +export class MediaBoxWrapper extends BaseComponent { + #thumbnailContainer = null; + #imageLinkElement = null; + + /** @type {Map|null} */ + #tagsAndAliases = null; + + init() { + this.#thumbnailContainer = this.container.querySelector('.image-container.thumb'); + this.#imageLinkElement = this.#thumbnailContainer.querySelector('a'); + } + + #calculateMediaBoxTags() { + /** @type {string[]|string[]} */ + const + tagAliases = this.#thumbnailContainer.dataset.imageTagAliases?.split(', ') || [], + actualTags = this.#imageLinkElement.title.split(' | Tagged: ')[1]?.split(', ') || []; + + /** @type {Map} */ + const tagAliasesMap = new Map(); + + for (let tagName of actualTags) { + tagAliasesMap.set(tagName, tagName); + } + + let currentRealTagName = null; + + for (let tagName of tagAliases) { + if (tagAliasesMap.has(tagName)) { + currentRealTagName = tagName; + continue; + } + + if (!currentRealTagName) { + console.warn('No real tag found for the alias:', tagName); + continue; + } + + tagAliasesMap.set(tagName, currentRealTagName); + } + + return tagAliasesMap; + } + + get tagsAndAliases() { + if (!this.#tagsAndAliases) { + this.#tagsAndAliases = this.#calculateMediaBoxTags(); + } + + return this.#tagsAndAliases; + } +} + +/** + * Wrap the media box element into the special wrapper. + * @param {HTMLElement} mediaBoxContainer + * @param {HTMLElement[]} childComponentElements + */ +export function initializeMediaBox(mediaBoxContainer, childComponentElements) { + new MediaBoxWrapper(mediaBoxContainer) + .initialize(); + + for (let childComponentElement of childComponentElements) { + mediaBoxContainer.appendChild(childComponentElement); + getComponent(childComponentElement)?.initialize(); + } +}