Enhance card section filter: multi-term OR/AND, filtered count badge
Space-separated terms use OR logic, comma-separated use AND. Count badge shows visible/total when filter is active. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -143,9 +143,9 @@ export class CardSection {
|
|||||||
|
|
||||||
this._lastItems = items;
|
this._lastItems = items;
|
||||||
|
|
||||||
// Update count badge
|
// Update count badge (will be refined by _applyFilter if a filter is active)
|
||||||
const countEl = document.querySelector(`[data-cs-toggle="${this.sectionKey}"] .cs-count`);
|
const countEl = document.querySelector(`[data-cs-toggle="${this.sectionKey}"] .cs-count`);
|
||||||
if (countEl) countEl.textContent = items.length;
|
if (countEl && !this._filterValue) countEl.textContent = items.length;
|
||||||
|
|
||||||
const newMap = new Map(items.map(i => [i.key, i.html]));
|
const newMap = new Map(items.map(i => [i.key, i.html]));
|
||||||
const addCard = content.querySelector('.cs-add-card');
|
const addCard = content.querySelector('.cs-add-card');
|
||||||
@@ -229,15 +229,32 @@ export class CardSection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_applyFilter(content, query) {
|
_applyFilter(content, query) {
|
||||||
const lower = query.toLowerCase();
|
|
||||||
const cards = content.querySelectorAll('.card, .template-card:not(.add-template-card)');
|
const cards = content.querySelectorAll('.card, .template-card:not(.add-template-card)');
|
||||||
const addCard = content.querySelector('.cs-add-card');
|
const addCard = content.querySelector('.cs-add-card');
|
||||||
|
const countEl = document.querySelector(`[data-cs-toggle="${this.sectionKey}"] .cs-count`);
|
||||||
|
const total = cards.length;
|
||||||
|
|
||||||
|
if (!query) {
|
||||||
|
cards.forEach(card => { card.style.display = ''; });
|
||||||
|
if (addCard) addCard.style.display = '';
|
||||||
|
if (countEl) countEl.textContent = total;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const lower = query.toLowerCase();
|
||||||
|
// Comma-separated segments → AND; spaces within a segment → OR
|
||||||
|
const groups = lower.split(',').map(g => g.trim().split(/\s+/).filter(Boolean)).filter(g => g.length);
|
||||||
|
let visible = 0;
|
||||||
|
|
||||||
cards.forEach(card => {
|
cards.forEach(card => {
|
||||||
const text = card.textContent.toLowerCase();
|
const text = card.textContent.toLowerCase();
|
||||||
card.style.display = (!lower || text.includes(lower)) ? '' : 'none';
|
// Each group must have at least one matching term (AND of ORs)
|
||||||
|
const match = groups.every(orTerms => orTerms.some(term => text.includes(term)));
|
||||||
|
card.style.display = match ? '' : 'none';
|
||||||
|
if (match) visible++;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (addCard) addCard.style.display = lower ? 'none' : '';
|
if (addCard) addCard.style.display = 'none';
|
||||||
|
if (countEl) countEl.textContent = `${visible}/${total}`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user