diff --git a/static/css/components/lora-modal/lora-modal.css b/static/css/components/lora-modal/lora-modal.css index 728d7d5f..50a21528 100644 --- a/static/css/components/lora-modal/lora-modal.css +++ b/static/css/components/lora-modal/lora-modal.css @@ -107,25 +107,13 @@ opacity: 0.5; } -.save-btn { - padding: 4px 8px; - background: var(--lora-accent); - border: none; - border-radius: var(--border-radius-xs); - color: white; - cursor: pointer; - transition: opacity 0.2s; - display: flex; - align-items: center; - justify-content: center; -} - -.save-btn:hover { - opacity: 0.9; -} - -.save-btn i { - font-size: 0.9em; +.notes-hint { + font-size: 0.8em; + color: var(--text-color); + opacity: 0.7; + margin-left: 5px; + cursor: help; + position: relative; /* Add positioning context */ } @media (max-width: 640px) { diff --git a/static/js/components/loraModal/index.js b/static/js/components/loraModal/index.js index f78e7be3..1fe83ae1 100644 --- a/static/js/components/loraModal/index.js +++ b/static/js/components/loraModal/index.js @@ -116,12 +116,9 @@ export function showLoraModal(lora) { ${renderTriggerWords(escapedWords, lora.file_path)}
- +
${lora.notes || 'Add your notes here...'}
-
@@ -171,7 +168,14 @@ export function showLoraModal(lora) {
`; - modalManager.showModal('loraModal', content); + modalManager.showModal('loraModal', content, null, function() { + // Clean up all handlers when modal closes + const modalElement = document.getElementById('loraModal'); + if (modalElement && modalElement._clickHandler) { + modalElement.removeEventListener('click', modalElement._clickHandler); + delete modalElement._clickHandler; + } + }); setupEditableFields(lora.file_path); setupShowcaseScroll('loraModal'); setupTabSwitching(); @@ -206,8 +210,11 @@ export function showLoraModal(lora) { function setupEventHandlers(filePath) { const modalElement = document.getElementById('loraModal'); - // Use event delegation to handle clicks - modalElement.addEventListener('click', async (event) => { + // Remove existing event listeners first + modalElement.removeEventListener('click', handleModalClick); + + // Create and store the handler function + function handleModalClick(event) { const target = event.target.closest('[data-action]'); if (!target) return; @@ -217,16 +224,17 @@ function setupEventHandlers(filePath) { case 'close-modal': modalManager.closeModal('loraModal'); break; - - case 'save-notes': - await saveNotes(filePath); - break; - case 'scroll-to-top': scrollToTop(target); break; } - }); + } + + // Add the event listener with the named function + modalElement.addEventListener('click', handleModalClick); + + // Store reference to the handler on the element for potential cleanup + modalElement._clickHandler = handleModalClick; } async function saveNotes(filePath) { diff --git a/static/js/managers/ModalManager.js b/static/js/managers/ModalManager.js index 636c36a4..356f1272 100644 --- a/static/js/managers/ModalManager.js +++ b/static/js/managers/ModalManager.js @@ -299,7 +299,7 @@ export class ModalManager { return null; } - showModal(id, content = null, onCloseCallback = null) { + showModal(id, content = null, onCloseCallback = null, cleanupCallback = null) { const modal = this.getModal(id); if (!modal) return; @@ -314,9 +314,8 @@ export class ModalManager { } // Store callback - if (onCloseCallback) { - modal.onCloseCallback = onCloseCallback; - } + modal.onCloseCallback = onCloseCallback; + modal.cleanupCallback = cleanupCallback; // Store current scroll position before showing modal this.scrollPosition = window.scrollY; @@ -362,6 +361,11 @@ export class ModalManager { modal.onCloseCallback(); modal.onCloseCallback = null; } + + if (modal.cleanupCallback) { + modal.cleanupCallback(); + modal.cleanupCallback = null; + } } handleEscape(e) {