diff --git a/web/js/autocomplete.js b/web/js/autocomplete.js index 5f33ddc..b2b7061 100644 --- a/web/js/autocomplete.js +++ b/web/js/autocomplete.js @@ -733,7 +733,6 @@ function insertTag(inputElement, tagToInsert) { const needsSuffixAfter = text[replaceEnd] !== ',' const suffix = needsSuffixAfter ? ', ' : ''; - // Text to insert (including prefix and suffix) const textToInsertWithAffixes = prefix + normalizedTag + suffix; // --- Use execCommand for Undo support --- @@ -757,28 +756,22 @@ function insertTag(inputElement, tagToInsert) { // Trigger input event manually as a fallback inputElement.dispatchEvent(new Event('input', { bubbles: true })); } - - // Note: execCommand usually triggers the necessary events, - // so explicitly dispatching 'input' might be redundant or cause issues. - // Test carefully. If ComfyUI doesn't update, uncomment the dispatchEvent line in the fallback. - // inputElement.dispatchEvent(new Event('input', { bubbles: true })); // Keep commented unless needed } export class AutocompleteEventHandler { + + /** + * + * @param {InputEvent} event + * @returns + */ handleInput(event) { if (!settingValues.enabled || !autocompleteUI) return; - if(!event.isTrusted) return; // ignore synthetic events - const ESCAPE_SEQUENCE = ["#", "/"]; // prevent autocomplete for these sequences const textareaElement = event.target; const partialTag = getCurrentPartialTag(textareaElement); - if (partialTag.length > 0 && !ESCAPE_SEQUENCE.some(seq => partialTag.startsWith(seq))) { - const candidates = findCompletionCandidates(partialTag); - autocompleteUI.show(textareaElement, candidates); - - // console.debug(`[Autocomplete-Plus] InputEvent: ${candidates.length} candidates for "${partialTag}"`); - } else { + if (partialTag.length <= 0){ autocompleteUI.hide(); } } @@ -800,6 +793,11 @@ export class AutocompleteEventHandler { }, 150); } + /** + * + * @param {KeyboardEvent} event + * @returns + */ handleKeyDown(event) { if (!settingValues.enabled) return; @@ -821,10 +819,8 @@ export class AutocompleteEventHandler { if (autocompleteUI.getSelectedTag() !== null) { event.preventDefault(); insertTag(textareaElement, autocompleteUI.getSelectedTag()); - } else { - // Allow default Tab/Enter if no item is selected - autocompleteUI.hide(); } + autocompleteUI.hide(); break; case 'Escape': event.preventDefault(); @@ -832,17 +828,55 @@ export class AutocompleteEventHandler { break; } } - + // Debug print - const partialTag = getCurrentPartialTag(textareaElement); - console.debug(`[Autocomplete-Plus] KeyDownEvent: ${event.key}, PartialTag: "${partialTag}"`); + // const partialTag = getCurrentPartialTag(textareaElement); + // console.debug(`[Autocomplete-Plus] KeyDownEvent: ${event.key}, PartialTag: "${partialTag}"`); } - // New event handler for mousemove to show similar tags on hover + /** + * + * @param {KeyboardEvent} event + * @returns + */ + handleKeyUp(event){ + + } + + /** + * + * @param {KeyboardEvent} event + * @returns + */ + handleKeyPress(event){ + if (!settingValues.enabled || !autocompleteUI) return; + if (event.defaultPrevented) return; // Ignore if default action is prevented + + const textareaElement = event.target; + + const ESCAPE_SEQUENCE = ["#", "/"]; // If the first string is that character, autocomplete will not be displayed. + const partialTag = getCurrentPartialTag(textareaElement); + if (partialTag.length > 0 && !ESCAPE_SEQUENCE.some(seq => partialTag.startsWith(seq))) { + const candidates = findCompletionCandidates(partialTag); + autocompleteUI.show(textareaElement, candidates); + + // console.debug(`[Autocomplete-Plus] KeyPressEvent: ${candidates.length} candidates for "${partialTag}"`); + } + } + + /** + * + * @param {MouseEvent} event + * @returns + */ handleMouseMove(event) { } - // New event handler for click to show similar tags + /** + * + * @param {MouseEvent} event + * @returns + */ handleClick(event) { if (!settingValues.enabled || !settingValues.enableSimilarTags || settingValues.similarTagsDisplayMode !== 'click') return; diff --git a/web/js/main.js b/web/js/main.js index 290a308..dfd2c62 100644 --- a/web/js/main.js +++ b/web/js/main.js @@ -19,6 +19,8 @@ function initializeEventHandlers() { element.addEventListener('focus', handleFocus); element.addEventListener('blur', handleBlur); element.addEventListener('keydown', handleKeyDown); + element.addEventListener('keyup', handleKeyUp); + element.addEventListener('keypress', handleKeyPress); // Add new event listeners for similar tags feature element.addEventListener('mousemove', handleMouseMove); @@ -100,6 +102,16 @@ function initializeEventHandlers() { autocompleteEventHandler.handleKeyDown(event); similarTagsEventHandler.handleKeyDown(event); } + + function handleKeyUp(event) { + autocompleteEventHandler.handleKeyUp(event); + similarTagsEventHandler.handleKeyUp(event); + } + + function handleKeyPress(event) { + autocompleteEventHandler.handleKeyPress(event); + similarTagsEventHandler.handleKeyPress(event); + } // New event handler for mousemove to show similar tags on hover function handleMouseMove(event) { diff --git a/web/js/similar-tags.js b/web/js/similar-tags.js index 7102f7a..ce44f49 100644 --- a/web/js/similar-tags.js +++ b/web/js/similar-tags.js @@ -580,6 +580,10 @@ export class SimilarTagsEventHandler { } + /** + * + * @param {KeyboardEvent} event + */ handleInput(event) { if (settingValues.enableSimilarTags) { if (similarTagsUI && similarTagsUI.isVisible()) { @@ -588,10 +592,18 @@ export class SimilarTagsEventHandler { } } + /** + * + * @param {KeyboardEvent} event + */ handleFocus(event) { // Handle focus event } + /** + * + * @param {KeyboardEvent} event + */ handleBlur(event) { if (!settingValues._hideWhenOutofFocus) { return; @@ -612,6 +624,10 @@ export class SimilarTagsEventHandler { }, 150); // Delay in milliseconds (adjust if necessary) } + /** + * + * @param {KeyboardEvent} event + */ handleKeyDown(event) { const textareaElement = event.target; @@ -625,17 +641,43 @@ export class SimilarTagsEventHandler { // Show similar tags on Ctrl+Space if (settingValues.enableSimilarTags) { - if (event.key === ' ' && event.ctrlKey) { + if (event.key === ' ' && event.ctrlKey && event.shiftKey ) { event.preventDefault(); showSimilarTagsForCurrentPosition(textareaElement); } } } + /** + * + * @param {KeyboardEvent} event + */ + handleKeyUp(event){ + + } + + /** + * + * @param {KeyboardEvent} event + */ + handleKeyPress(event){ + + } + + /** + * + * @param {MouseEvent} event + * @returns + */ handleMouseMove(event) { } + /** + * + * @param {MouseEvent} event + * @returns + */ handleClick(event) { const textareaElement = event.target; showSimilarTagsForCurrentPosition(textareaElement);