Fix hierarchical autocomplete: select directory segments, not files; stop when direction subdir is found
This commit is contained in:
@@ -16,22 +16,57 @@ def _discover_directories():
|
|||||||
return []
|
return []
|
||||||
|
|
||||||
candidates = set()
|
candidates = set()
|
||||||
for root, subdirs, _ in os.walk(base_dir, followlinks=True):
|
|
||||||
|
for root, dirs, files in os.walk(base_dir, followlinks=True):
|
||||||
rel = os.path.relpath(root, base_dir)
|
rel = os.path.relpath(root, base_dir)
|
||||||
subdirs_lower = {s.lower() for s in subdirs}
|
if rel == ".":
|
||||||
if VALID_DIRECTIONS & subdirs_lower or VALID_MODALITIES & subdirs_lower:
|
continue
|
||||||
if rel == ".":
|
|
||||||
continue
|
dirs_lower = {d.lower() for d in dirs}
|
||||||
|
|
||||||
|
if VALID_DIRECTIONS & dirs_lower:
|
||||||
|
candidates.add(rel)
|
||||||
|
elif VALID_MODALITIES & dirs_lower:
|
||||||
candidates.add(rel)
|
candidates.add(rel)
|
||||||
|
|
||||||
return sorted(candidates)
|
return sorted(candidates)
|
||||||
|
|
||||||
|
|
||||||
def _resolve_target_dir(base_dir, directory, direction):
|
def _discover_children(parent_rel):
|
||||||
if directory and (not isinstance(directory, str) or directory.strip()):
|
base_dir = folder_paths.get_input_directory()
|
||||||
path = os.path.join(base_dir, directory)
|
if parent_rel:
|
||||||
|
parent_abs = os.path.join(base_dir, parent_rel)
|
||||||
else:
|
else:
|
||||||
path = base_dir
|
parent_abs = base_dir
|
||||||
|
|
||||||
|
if not os.path.isdir(parent_abs):
|
||||||
|
return []
|
||||||
|
|
||||||
|
children = set()
|
||||||
|
try:
|
||||||
|
for name in os.listdir(parent_abs):
|
||||||
|
full = os.path.join(parent_abs, name)
|
||||||
|
if os.path.isdir(full):
|
||||||
|
rel = os.path.relpath(full, base_dir)
|
||||||
|
children.add(rel)
|
||||||
|
except OSError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
my_children = set()
|
||||||
|
for child in children:
|
||||||
|
child_parts = child.split("/")
|
||||||
|
parent_parts = parent_rel.split("/") if parent_rel else []
|
||||||
|
if len(child_parts) == len(parent_parts) + 1:
|
||||||
|
my_children.add(child_parts[-1])
|
||||||
|
|
||||||
|
return sorted(my_children)
|
||||||
|
|
||||||
|
|
||||||
|
def _resolve_target_dir(base_dir, directory, direction):
|
||||||
|
if not directory or not (isinstance(directory, str) and directory.strip()):
|
||||||
|
raise ValueError("directory must be a non-empty string")
|
||||||
|
|
||||||
|
path = os.path.join(base_dir, directory.strip())
|
||||||
|
|
||||||
if direction and direction.strip():
|
if direction and direction.strip():
|
||||||
path = os.path.join(path, direction.strip())
|
path = os.path.join(path, direction.strip())
|
||||||
@@ -42,7 +77,8 @@ def _resolve_target_dir(base_dir, directory, direction):
|
|||||||
def _list_image_files(target_dir):
|
def _list_image_files(target_dir):
|
||||||
try:
|
try:
|
||||||
files = [
|
files = [
|
||||||
f for f in sorted(os.listdir(target_dir))
|
f
|
||||||
|
for f in sorted(os.listdir(target_dir))
|
||||||
if os.path.isfile(os.path.join(target_dir, f))
|
if os.path.isfile(os.path.join(target_dir, f))
|
||||||
and os.path.splitext(f)[1].lower() in SUPPORTED_EXTENSIONS
|
and os.path.splitext(f)[1].lower() in SUPPORTED_EXTENSIONS
|
||||||
]
|
]
|
||||||
@@ -58,14 +94,12 @@ def _resize_image(image, target_w, target_h):
|
|||||||
return image, orig_w, orig_h
|
return image, orig_w, orig_h
|
||||||
|
|
||||||
if target_w > 0 and target_h == 0:
|
if target_w > 0 and target_h == 0:
|
||||||
fw = target_w
|
|
||||||
fh = max(1, int(orig_h * (target_w / orig_w)))
|
fh = max(1, int(orig_h * (target_w / orig_w)))
|
||||||
return image.resize((fw, fh), Image.Resampling.LANCZOS), fw, fh
|
return image.resize((target_w, fh), Image.Resampling.LANCZOS), target_w, fh
|
||||||
|
|
||||||
if target_h > 0 and target_w == 0:
|
if target_h > 0 and target_w == 0:
|
||||||
fh = target_h
|
|
||||||
fw = max(1, int(orig_w * (target_h / orig_h)))
|
fw = max(1, int(orig_w * (target_h / orig_h)))
|
||||||
return image.resize((fw, fh), Image.Resampling.LANCZOS), fw, fh
|
return image.resize((fw, target_h), Image.Resampling.LANCZOS), fw, target_h
|
||||||
|
|
||||||
scale = max(target_w / orig_w, target_h / orig_h)
|
scale = max(target_w / orig_w, target_h / orig_h)
|
||||||
new_w = max(1, int(orig_w * scale))
|
new_w = max(1, int(orig_w * scale))
|
||||||
@@ -98,7 +132,9 @@ class CompassImageLoader:
|
|||||||
RETURN_NAMES = ("IMAGE", "path", "width", "height", "frame_count")
|
RETURN_NAMES = ("IMAGE", "path", "width", "height", "frame_count")
|
||||||
FUNCTION = "load_images"
|
FUNCTION = "load_images"
|
||||||
|
|
||||||
def load_images(self, directory, direction, modality, frame=None, width=0, height=0):
|
def load_images(
|
||||||
|
self, directory, direction, modality, frame=None, width=0, height=0
|
||||||
|
):
|
||||||
base_dir = folder_paths.get_input_directory()
|
base_dir = folder_paths.get_input_directory()
|
||||||
target_dir = _resolve_target_dir(base_dir, directory, direction)
|
target_dir = _resolve_target_dir(base_dir, directory, direction)
|
||||||
modality_path = os.path.join(target_dir, modality)
|
modality_path = os.path.join(target_dir, modality)
|
||||||
@@ -110,7 +146,6 @@ class CompassImageLoader:
|
|||||||
if not files:
|
if not files:
|
||||||
raise RuntimeError(f"No images found in: {modality_path}")
|
raise RuntimeError(f"No images found in: {modality_path}")
|
||||||
|
|
||||||
# Frame selection
|
|
||||||
if frame is None or str(frame).strip() == "":
|
if frame is None or str(frame).strip() == "":
|
||||||
selected_files = files
|
selected_files = files
|
||||||
output_path = modality_path
|
output_path = modality_path
|
||||||
@@ -131,7 +166,6 @@ class CompassImageLoader:
|
|||||||
selected_files = [files[index]]
|
selected_files = [files[index]]
|
||||||
output_path = os.path.join(modality_path, files[index])
|
output_path = os.path.join(modality_path, files[index])
|
||||||
|
|
||||||
# Load and process images
|
|
||||||
tensors = []
|
tensors = []
|
||||||
final_w, final_h = 0, 0
|
final_w, final_h = 0, 0
|
||||||
|
|
||||||
@@ -150,7 +184,9 @@ class CompassImageLoader:
|
|||||||
return (image_batch, output_path, final_w, final_h, len(selected_files))
|
return (image_batch, output_path, final_w, final_h, len(selected_files))
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def IS_CHANGED(cls, directory, direction, modality, frame=None, width=0, height=0):
|
def IS_CHANGED(
|
||||||
|
cls, directory, direction, modality, frame=None, width=0, height=0
|
||||||
|
):
|
||||||
import hashlib
|
import hashlib
|
||||||
|
|
||||||
base_dir = folder_paths.get_input_directory()
|
base_dir = folder_paths.get_input_directory()
|
||||||
@@ -162,7 +198,9 @@ class CompassImageLoader:
|
|||||||
|
|
||||||
files = _list_image_files(modality_path)
|
files = _list_image_files(modality_path)
|
||||||
m = hashlib.sha256()
|
m = hashlib.sha256()
|
||||||
m.update(f"{directory}|{direction}|{modality}|{frame}|{width}|{height}".encode())
|
m.update(
|
||||||
|
f"{directory}|{direction}|{modality}|{frame}|{width}|{height}".encode()
|
||||||
|
)
|
||||||
|
|
||||||
if frame is None or str(frame).strip() == "":
|
if frame is None or str(frame).strip() == "":
|
||||||
for f in files:
|
for f in files:
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import { app } from "../../../scripts/app.js";
|
import { app } from "../../../scripts/app.js";
|
||||||
import { api } from "../../../scripts/api.js";
|
|
||||||
|
|
||||||
function getAllNodesOfType(type) {
|
function getAllNodesOfType(type) {
|
||||||
const nodes = [];
|
const nodes = [];
|
||||||
@@ -9,49 +8,32 @@ function getAllNodesOfType(type) {
|
|||||||
return nodes;
|
return nodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseDirectorySegments(value) {
|
function filterChildDirs(allDirs, parentPrefix) {
|
||||||
const parts = value.split("/").filter(Boolean);
|
const prefixNorm = parentPrefix.replace(/\/$/, "").toLowerCase();
|
||||||
return {
|
const results = [];
|
||||||
prefix: parts.length > 0 ? parts.slice(0, -1).join("/") : "",
|
|
||||||
filter: parts.length > 0 ? parts[parts.length - 1] : value,
|
for (const dir of allDirs) {
|
||||||
isAtStart: !value.endsWith("/"),
|
const parts = dir.split("/").filter(Boolean);
|
||||||
};
|
if (parts.length < 1) continue;
|
||||||
|
|
||||||
|
const parent = parts.slice(0, -1).join("/").toLowerCase();
|
||||||
|
const child = parts[parts.length - 1];
|
||||||
|
|
||||||
|
if (parent === prefixNorm) {
|
||||||
|
results.push(child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return [...new Set(results)].sort();
|
||||||
}
|
}
|
||||||
|
|
||||||
function filterDirectories(allDirs, prefix, filter) {
|
function showDropdown(listEl, items, directoryWidget, inputEl) {
|
||||||
const prefixLower = prefix.toLowerCase();
|
|
||||||
const filterLower = filter.toLowerCase();
|
|
||||||
|
|
||||||
return allDirs
|
|
||||||
.filter((d) => {
|
|
||||||
const dParts = d.split("/").filter(Boolean);
|
|
||||||
if (prefixLower) {
|
|
||||||
if (dParts.length < 2) return false;
|
|
||||||
const dirPrefix = dParts.slice(0, -1).join("/").toLowerCase();
|
|
||||||
if (dirPrefix !== prefixLower) return false;
|
|
||||||
} else {
|
|
||||||
if (dParts.length < 1) return false;
|
|
||||||
}
|
|
||||||
const lastPart = dParts[dParts.length - 1].toLowerCase();
|
|
||||||
return lastPart.startsWith(filterLower);
|
|
||||||
})
|
|
||||||
.map((d) => {
|
|
||||||
const dParts = d.split("/").filter(Boolean);
|
|
||||||
return dParts[prefix ? dParts.length - 1 : dParts.length - 1];
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function uniqueSorted(arr) {
|
|
||||||
return [...new Set(arr)].sort();
|
|
||||||
}
|
|
||||||
|
|
||||||
function showDropdown(listEl, items, widget, inputEl) {
|
|
||||||
listEl.innerHTML = "";
|
listEl.innerHTML = "";
|
||||||
if (items.length === 0) {
|
if (items.length === 0) {
|
||||||
listEl.style.display = "none";
|
listEl.style.display = "none";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
items.forEach((item) => {
|
for (const item of items) {
|
||||||
const li = document.createElement("li");
|
const li = document.createElement("li");
|
||||||
li.textContent = item;
|
li.textContent = item;
|
||||||
li.style.padding = "4px 8px";
|
li.style.padding = "4px 8px";
|
||||||
@@ -59,29 +41,30 @@ function showDropdown(listEl, items, widget, inputEl) {
|
|||||||
li.style.color = "#ccc";
|
li.style.color = "#ccc";
|
||||||
li.style.listStyle = "none";
|
li.style.listStyle = "none";
|
||||||
li.addEventListener("mouseenter", () => {
|
li.addEventListener("mouseenter", () => {
|
||||||
document.querySelectorAll("#compass_dir_list li").forEach((el) => {
|
listEl.querySelectorAll("li").forEach((el) => (el.style.background = "transparent"));
|
||||||
el.style.background = "transparent";
|
|
||||||
});
|
|
||||||
li.style.background = "#444";
|
li.style.background = "#444";
|
||||||
});
|
});
|
||||||
li.addEventListener("click", () => {
|
li.addEventListener("click", () => {
|
||||||
const newValue = inputEl._prefix + item + "/";
|
const newValue = inputEl._currentPrefix + item + "/";
|
||||||
inputEl.value = newValue;
|
inputEl.value = newValue;
|
||||||
inputEl._prefix = newValue;
|
inputEl._currentPrefix = newValue;
|
||||||
widget.value = newValue;
|
directoryWidget.value = newValue;
|
||||||
listEl.innerHTML = "";
|
hideDropdown(listEl);
|
||||||
inputEl.focus();
|
inputEl.focus();
|
||||||
});
|
});
|
||||||
listEl.appendChild(li);
|
listEl.appendChild(li);
|
||||||
|
}
|
||||||
|
|
||||||
|
Object.assign(listEl.style, {
|
||||||
|
display: "block",
|
||||||
|
background: "#222",
|
||||||
|
border: "1px solid #444",
|
||||||
|
position: "absolute",
|
||||||
|
zIndex: "9999",
|
||||||
|
width: inputEl.offsetWidth + "px",
|
||||||
|
maxHeight: "200px",
|
||||||
|
overflowY: "auto",
|
||||||
});
|
});
|
||||||
listEl.style.display = "block";
|
|
||||||
listEl.style.background = "#222";
|
|
||||||
listEl.style.border = "1px solid #444";
|
|
||||||
listEl.style.position = "absolute";
|
|
||||||
listEl.style.zIndex = "1000";
|
|
||||||
listEl.style.width = inputEl.offsetWidth + "px";
|
|
||||||
listEl.style.maxHeight = "200px";
|
|
||||||
listEl.style.overflowY = "auto";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function hideDropdown(listEl) {
|
function hideDropdown(listEl) {
|
||||||
@@ -89,58 +72,6 @@ function hideDropdown(listEl) {
|
|||||||
listEl.style.display = "none";
|
listEl.style.display = "none";
|
||||||
}
|
}
|
||||||
|
|
||||||
function setupAutocomplete(node, directoryWidget, inputEl, listEl) {
|
|
||||||
inputEl._prefix = directoryWidget.value || "";
|
|
||||||
inputEl._all_values = [...(directoryWidget._all_values || [])];
|
|
||||||
|
|
||||||
inputEl.addEventListener("input", () => {
|
|
||||||
const value = inputEl.value;
|
|
||||||
const { prefix, filter, isAtStart } = parseDirectorySegments(value);
|
|
||||||
|
|
||||||
// Determine the effective prefix: use everything up to the last slash
|
|
||||||
let effectivePrefix = "";
|
|
||||||
const lastSlash = value.lastIndexOf("/");
|
|
||||||
if (lastSlash >= 0) {
|
|
||||||
effectivePrefix = value.substring(0, lastSlash + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
const items = filterDirectories(inputEl._all_values, effectivePrefix, filter);
|
|
||||||
const unique = uniqueSorted(items);
|
|
||||||
showDropdown(listEl, unique, directoryWidget, inputEl);
|
|
||||||
|
|
||||||
// Sync prefix back
|
|
||||||
inputEl._prefix = effectivePrefix;
|
|
||||||
});
|
|
||||||
|
|
||||||
inputEl.addEventListener("keydown", (e) => {
|
|
||||||
if (e.key === "Escape") {
|
|
||||||
hideDropdown(listEl);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (e.key === "Enter" || e.key === "Tab") {
|
|
||||||
const visible = listEl.querySelectorAll("li");
|
|
||||||
if (visible.length === 1) {
|
|
||||||
visible[0].click();
|
|
||||||
e.preventDefault();
|
|
||||||
} else if (visible.length > 0) {
|
|
||||||
// If user presses Tab with multiple options, pick the first match
|
|
||||||
visible[0].click();
|
|
||||||
e.preventDefault();
|
|
||||||
} else {
|
|
||||||
hideDropdown(listEl);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
inputEl.addEventListener("blur", () => {
|
|
||||||
setTimeout(() => {
|
|
||||||
if (!listEl.contains(document.activeElement)) {
|
|
||||||
hideDropdown(listEl);
|
|
||||||
}
|
|
||||||
}, 150);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
app.registerExtension({
|
app.registerExtension({
|
||||||
name: "CompassImageLoader",
|
name: "CompassImageLoader",
|
||||||
|
|
||||||
@@ -154,49 +85,112 @@ app.registerExtension({
|
|||||||
const directoryWidget = this.widgets?.find((w) => w.name === "directory");
|
const directoryWidget = this.widgets?.find((w) => w.name === "directory");
|
||||||
if (!directoryWidget) return;
|
if (!directoryWidget) return;
|
||||||
|
|
||||||
// Build the full list from the node definition values
|
|
||||||
const defDirs = nodeData.input?.required?.directory;
|
const defDirs = nodeData.input?.required?.directory;
|
||||||
if (defDirs && Array.isArray(defDirs[0])) {
|
directoryWidget._all_values = defDirs && Array.isArray(defDirs[0]) ? defDirs[0] : [];
|
||||||
directoryWidget._all_values = defDirs[0];
|
|
||||||
} else {
|
|
||||||
directoryWidget._all_values = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find or create the text input for filtering
|
|
||||||
const filterWidget = this.widgets?.find((w) => w.name === "directory_filter");
|
const filterWidget = this.widgets?.find((w) => w.name === "directory_filter");
|
||||||
const inputEl = filterWidget?.inputEl;
|
const inputEl = filterWidget?.inputEl;
|
||||||
|
if (!inputEl) return;
|
||||||
|
|
||||||
if (inputEl) {
|
const listEl = document.createElement("ul");
|
||||||
// Create dropdown list element
|
listEl.style.display = "none";
|
||||||
const listEl = document.createElement("ul");
|
document.body.appendChild(listEl);
|
||||||
listEl.id = "compass_dir_list";
|
|
||||||
listEl.style.display = "none";
|
|
||||||
listEl.style.position = "absolute";
|
|
||||||
listEl.style.zIndex = "9999";
|
|
||||||
document.body.appendChild(listEl);
|
|
||||||
|
|
||||||
inputEl._prefix = directoryWidget.value || "";
|
inputEl._currentPrefix = directoryWidget.value || "";
|
||||||
setupAutocomplete(this, directoryWidget, inputEl, listEl);
|
|
||||||
|
|
||||||
// When the original combo value changes from workflow load, sync
|
inputEl.addEventListener("input", () => {
|
||||||
const origSetValue = directoryWidget.callback
|
const val = inputEl.value;
|
||||||
? directoryWidget.callback
|
const lastSlash = val.lastIndexOf("/");
|
||||||
: () => {};
|
|
||||||
directoryWidget.callback = (value) => {
|
let prefix, filter;
|
||||||
origSetValue.call(directoryWidget, value);
|
if (lastSlash >= 0) {
|
||||||
if (inputEl) {
|
prefix = val.substring(0, lastSlash + 1);
|
||||||
inputEl._prefix = value || "";
|
filter = val.substring(lastSlash + 1);
|
||||||
inputEl.value = value || "";
|
} else {
|
||||||
|
prefix = "";
|
||||||
|
filter = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prefix) {
|
||||||
|
const cleanPrefix = prefix.replace(/\/$/, "");
|
||||||
|
const candidates = filterChildDirs(directoryWidget._all_values, cleanPrefix);
|
||||||
|
const filtered = filter
|
||||||
|
? candidates.filter((c) => c.toLowerCase().startsWith(filter.toLowerCase()))
|
||||||
|
: candidates;
|
||||||
|
showDropdown(listEl, filtered, directoryWidget, inputEl);
|
||||||
|
} else {
|
||||||
|
const filtered = filter
|
||||||
|
? directoryWidget._all_values.filter((d) =>
|
||||||
|
d.toLowerCase().includes(filter.toLowerCase())
|
||||||
|
)
|
||||||
|
: [...new Set(directoryWidget._all_values.map((d) => d.split("/")[0]))].sort();
|
||||||
|
showDropdown(listEl, filtered, directoryWidget, inputEl);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
inputEl.addEventListener("focus", () => {
|
||||||
|
const val = inputEl.value;
|
||||||
|
const lastSlash = val.lastIndexOf("/");
|
||||||
|
|
||||||
|
if (lastSlash >= 0 && val.endsWith("/")) {
|
||||||
|
const prefix = val.replace(/\/$/, "");
|
||||||
|
inputEl._currentPrefix = prefix + "/";
|
||||||
|
const items = filterChildDirs(directoryWidget._all_values, prefix);
|
||||||
|
showDropdown(listEl, items, directoryWidget, inputEl);
|
||||||
|
} else if (lastSlash >= 0) {
|
||||||
|
const prefix = val.substring(0, lastSlash + 1);
|
||||||
|
inputEl._currentPrefix = prefix;
|
||||||
|
inputEl.focus();
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
inputEl._currentPrefix = "";
|
||||||
|
const items = filter
|
||||||
|
? directoryWidget._all_values.filter((d) =>
|
||||||
|
d.toLowerCase().includes(val.toLowerCase())
|
||||||
|
)
|
||||||
|
: [...new Set(directoryWidget._all_values.map((d) => d.split("/")[0]))].sort();
|
||||||
|
showDropdown(listEl, items, directoryWidget, inputEl);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
inputEl.addEventListener("blur", () => {
|
||||||
|
setTimeout(() => {
|
||||||
|
if (!listEl.contains(document.activeElement)) {
|
||||||
|
hideDropdown(listEl);
|
||||||
}
|
}
|
||||||
};
|
}, 150);
|
||||||
|
});
|
||||||
|
|
||||||
// Cleanup when node is removed
|
inputEl.addEventListener("keydown", (e) => {
|
||||||
const origOnRemoved = this.onRemoved;
|
if (e.key === "Escape") {
|
||||||
this.onRemoved = () => {
|
hideDropdown(listEl);
|
||||||
if (origOnRemoved) origOnRemoved.apply(this, []);
|
return;
|
||||||
listEl.remove();
|
}
|
||||||
};
|
if (e.key === "Enter" || e.key === "Tab") {
|
||||||
}
|
const visible = listEl.querySelectorAll("li");
|
||||||
|
if (visible.length === 1) {
|
||||||
|
visible[0].click();
|
||||||
|
e.preventDefault();
|
||||||
|
} else if (visible.length > 0) {
|
||||||
|
visible[0].click();
|
||||||
|
e.preventDefault();
|
||||||
|
}
|
||||||
|
hideDropdown(listEl);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const origSetValue = directoryWidget.callback ? directoryWidget.callback.bind(directoryWidget) : () => {};
|
||||||
|
directoryWidget.callback = (value) => {
|
||||||
|
origSetValue(value);
|
||||||
|
inputEl._currentPrefix = value || "";
|
||||||
|
inputEl.value = value || "";
|
||||||
|
};
|
||||||
|
|
||||||
|
const origOnRemoved = this.onRemoved ? this.onRemoved.bind(this) : () => {};
|
||||||
|
this.onRemoved = () => {
|
||||||
|
origOnRemoved();
|
||||||
|
listEl.remove();
|
||||||
|
};
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -204,14 +198,12 @@ app.registerExtension({
|
|||||||
if (node.type !== "CompassImageLoader") return;
|
if (node.type !== "CompassImageLoader") return;
|
||||||
|
|
||||||
const directoryWidget = node.widgets?.find((w) => w.name === "directory");
|
const directoryWidget = node.widgets?.find((w) => w.name === "directory");
|
||||||
if (!directoryWidget) return;
|
|
||||||
|
|
||||||
const filterWidget = node.widgets?.find((w) => w.name === "directory_filter");
|
const filterWidget = node.widgets?.find((w) => w.name === "directory_filter");
|
||||||
const inputEl = filterWidget?.inputEl;
|
const inputEl = filterWidget?.inputEl;
|
||||||
const listEl = document.getElementById("compass_dir_list");
|
const listEl = document.getElementById("compass_dir_list");
|
||||||
|
|
||||||
if (inputEl && listEl) {
|
if (inputEl && listEl) {
|
||||||
setupAutocomplete(node, directoryWidget, inputEl, listEl);
|
inputEl._currentPrefix = directoryWidget?.value || "";
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user