feat(context-menu): prevent duplicate NSFW selector initialization

Add initialization tracking to prevent multiple event listener attachments
in context menu components. Use dataset.initialized flag to ensure NSFW
selector events are only set up once per component instance.

In ModelContextMenuMixin, replace DOM elements and reattach event listeners
to avoid duplicates when components are reinitialized. This fixes issues
where multiple click handlers could be attached to the same elements.
This commit is contained in:
Will Miao
2025-10-17 10:52:02 +08:00
parent 61101a7ad0
commit 0ecbdf6f39
5 changed files with 35 additions and 15 deletions

View File

@@ -11,9 +11,10 @@ export class CheckpointContextMenu extends BaseContextMenu {
this.modelType = 'checkpoint';
this.resetAndReload = resetAndReload;
// Initialize NSFW Level Selector events
if (this.nsfwSelector) {
// Initialize NSFW Level Selector events only if not already initialized
if (this.nsfwSelector && !this.nsfwSelector.dataset.initialized) {
this.initNSFWSelector();
this.nsfwSelector.dataset.initialized = 'true';
}
}

View File

@@ -11,9 +11,10 @@ export class EmbeddingContextMenu extends BaseContextMenu {
this.modelType = 'embedding';
this.resetAndReload = resetAndReload;
// Initialize NSFW Level Selector events
if (this.nsfwSelector) {
// Initialize NSFW Level Selector events only if not already initialized
if (this.nsfwSelector && !this.nsfwSelector.dataset.initialized) {
this.initNSFWSelector();
this.nsfwSelector.dataset.initialized = 'true';
}
}

View File

@@ -12,9 +12,10 @@ export class LoraContextMenu extends BaseContextMenu {
this.modelType = 'lora';
this.resetAndReload = resetAndReload;
// Initialize NSFW Level Selector events
if (this.nsfwSelector) {
// Initialize NSFW Level Selector events only if not already initialized
if (this.nsfwSelector && !this.nsfwSelector.dataset.initialized) {
this.initNSFWSelector();
this.nsfwSelector.dataset.initialized = 'true';
}
}

View File

@@ -8,9 +8,12 @@ import { bulkManager } from '../../managers/BulkManager.js';
export const ModelContextMenuMixin = {
// NSFW Selector methods
initNSFWSelector() {
// Close button
// Remove any existing event listeners by cloning and replacing elements
// This is a simple way to ensure we don't have duplicate event listeners
const closeBtn = this.nsfwSelector.querySelector('.close-nsfw-selector');
closeBtn.addEventListener('click', () => {
const newCloseBtn = closeBtn.cloneNode(true);
closeBtn.parentNode.replaceChild(newCloseBtn, closeBtn);
newCloseBtn.addEventListener('click', () => {
this.nsfwSelector.style.display = 'none';
this.resetNSFWSelectorState();
});
@@ -18,8 +21,12 @@ export const ModelContextMenuMixin = {
// Level buttons
const levelButtons = this.nsfwSelector.querySelectorAll('.nsfw-level-btn');
levelButtons.forEach(btn => {
btn.addEventListener('click', async () => {
const level = parseInt(btn.dataset.level);
// Remove any existing event listeners by cloning and replacing the button
const newBtn = btn.cloneNode(true);
btn.parentNode.replaceChild(newBtn, btn);
newBtn.addEventListener('click', async () => {
const level = parseInt(newBtn.dataset.level);
const mode = this.nsfwSelector.dataset.mode || 'single';
if (mode === 'bulk') {
@@ -56,15 +63,24 @@ export const ModelContextMenuMixin = {
});
});
// Close when clicking outside
document.addEventListener('click', (e) => {
// Close when clicking outside - use a named function so we can remove it later
const outsideClickListener = (e) => {
if (this.nsfwSelector.style.display === 'block' &&
!this.nsfwSelector.contains(e.target) &&
!e.target.closest('.context-menu-item[data-action="set-nsfw"], .context-menu-item[data-action="set-content-rating"]')) {
this.nsfwSelector.style.display = 'none';
this.resetNSFWSelectorState();
}
});
};
// Remove previous listener if it exists
if (this._outsideClickListener) {
document.removeEventListener('click', this._outsideClickListener);
}
// Store and add new listener
this._outsideClickListener = outsideClickListener;
document.addEventListener('click', this._outsideClickListener);
},
resetNSFWSelectorState() {

View File

@@ -11,9 +11,10 @@ export class RecipeContextMenu extends BaseContextMenu {
this.nsfwSelector = document.getElementById('nsfwLevelSelector');
this.modelType = 'recipe';
// Initialize NSFW Level Selector events
if (this.nsfwSelector) {
// Initialize NSFW Level Selector events only if not already initialized
if (this.nsfwSelector && !this.nsfwSelector.dataset.initialized) {
this.initNSFWSelector();
this.nsfwSelector.dataset.initialized = 'true';
}
}