stylescape
Version:
Stylescape is a visual identity framework developed by Scape Agency.
110 lines • 3.81 kB
JavaScript
export class FilterManager {
constructor(inputSelectorOrElement, options = {}) {
this.debounceTimer = null;
this.handleInput = () => {
if (this.debounceTimer) {
clearTimeout(this.debounceTimer);
}
this.debounceTimer = window.setTimeout(() => {
this.filter();
}, this.options.debounce);
};
this.input =
typeof inputSelectorOrElement === "string"
? document.querySelector(inputSelectorOrElement)
: inputSelectorOrElement;
this.options = {
itemSelector: options.itemSelector ?? ".filter-item",
searchIn: options.searchIn ?? "textContent",
debounce: options.debounce ?? 150,
caseSensitive: options.caseSensitive ?? false,
minChars: options.minChars ?? 0,
hiddenClass: options.hiddenClass ?? "filter--hidden",
matchClass: options.matchClass ?? "filter--match",
onFilter: options.onFilter ?? (() => { }),
onEmpty: options.onEmpty ?? (() => { }),
};
this.items = [];
if (!this.input) {
console.warn("[Stylescape] FilterManager input not found");
return;
}
this.init();
}
filter(query) {
const searchQuery = query ?? this.input?.value ?? "";
return this.applyFilter(searchQuery);
}
clear() {
if (this.input) {
this.input.value = "";
}
this.showAll();
}
showAll() {
this.items.forEach((item) => {
item.classList.remove(this.options.hiddenClass);
item.classList.remove(this.options.matchClass);
});
}
refresh() {
this.items = Array.from(document.querySelectorAll(this.options.itemSelector));
}
getMatches() {
return this.items.filter((item) => !item.classList.contains(this.options.hiddenClass));
}
destroy() {
this.input?.removeEventListener("input", this.handleInput);
this.input = null;
this.items = [];
}
init() {
this.refresh();
this.input?.addEventListener("input", this.handleInput);
if (this.input?.value) {
this.filter();
}
}
applyFilter(query) {
if (query.length < this.options.minChars) {
this.showAll();
return this.items;
}
const normalizedQuery = this.options.caseSensitive
? query
: query.toLowerCase();
const matches = [];
this.items.forEach((item) => {
const content = this.getSearchContent(item);
const normalizedContent = this.options.caseSensitive
? content
: content.toLowerCase();
const isMatch = normalizedContent.includes(normalizedQuery);
item.classList.toggle(this.options.hiddenClass, !isMatch);
item.classList.toggle(this.options.matchClass, isMatch);
if (isMatch) {
matches.push(item);
}
});
this.options.onFilter(matches, query);
if (matches.length === 0 && query.length > 0) {
this.options.onEmpty(query);
}
return matches;
}
getSearchContent(item) {
const searchIn = Array.isArray(this.options.searchIn)
? this.options.searchIn
: [this.options.searchIn];
return searchIn
.map((attr) => {
if (attr === "textContent") {
return item.textContent || "";
}
return item.getAttribute(attr) || item.dataset[attr] || "";
})
.join(" ");
}
}
export default FilterManager;
//# sourceMappingURL=FilterManager.js.map