From 1004581ba401032b63d8fdf0dc6b0fb56ee65a12 Mon Sep 17 00:00:00 2001 From: matthewcsimpson Date: Tue, 14 Apr 2026 14:40:25 -0700 Subject: [PATCH] selected items persist --- Dist/WebflowOnly/CMSFilter.js | 6 +++++ __tests__/CMSFilter.test.js | 43 +++++++++++++++++++++++++++++++++++ docs/WebflowOnly/CMSFilter.md | 2 +- 3 files changed, 50 insertions(+), 1 deletion(-) diff --git a/Dist/WebflowOnly/CMSFilter.js b/Dist/WebflowOnly/CMSFilter.js index 0dcb606..fccf60c 100644 --- a/Dist/WebflowOnly/CMSFilter.js +++ b/Dist/WebflowOnly/CMSFilter.js @@ -852,6 +852,12 @@ class CMSFilter { } }); + // Hybrid only: keep selected options visible so users can change or clear them + // when other facets (e.g. make) rule them out of the current result set. + if (filteringMode === "hybrid" && istoggle.checked) { + isAvailable = true; + } + // Restore original display style or hide if (isAvailable) { // Restore original display style diff --git a/__tests__/CMSFilter.test.js b/__tests__/CMSFilter.test.js index ef5d188..295006d 100644 --- a/__tests__/CMSFilter.test.js +++ b/__tests__/CMSFilter.test.js @@ -239,6 +239,49 @@ describe("CMSFilter", () => { ]); }); + test("hybrid keeps checked body types visible when current make rules them out", () => { + document.body.innerHTML = ` +
+ + + + + +
+
+
+
T
+
H
+
+
+ `; + InitializeCMSFilter(); + const form = document.querySelector('[wt-cmsfilter-element="filter-form"]'); + const honda = Array.from( + form.querySelectorAll('label[wt-cmsfilter-category="make"]'), + ).find((l) => l.textContent.includes("Honda")); + const suv = Array.from( + form.querySelectorAll('label[wt-cmsfilter-category="bodytype"]'), + ).find((l) => l.textContent.includes("SUV")); + const hatch = Array.from( + form.querySelectorAll('label[wt-cmsfilter-category="bodytype"]'), + ).find((l) => l.textContent.includes("Hatchback")); + suv.querySelector("input").checked = true; + hatch.querySelector("input").checked = true; + honda.querySelector("input").checked = true; + [suv, hatch, honda].forEach((el) => + el + .querySelector("input") + .dispatchEvent(new Event("change", { bubbles: true })), + ); + const instance = window.webtricks[0].CMSFilter; + instance.ApplyFilters(); + + expect(instance.filteredItems.length).toBe(1); + expect(suv.style.display).not.toBe("none"); + expect(hatch.style.display).not.toBe("none"); + }); + test("hybrid with empty wt-cmsfilter-hybrid-categories narrows all facets like advanced", () => { buildHybridScenarioDOM("hybrid", ""); InitializeCMSFilter(); diff --git a/docs/WebflowOnly/CMSFilter.md b/docs/WebflowOnly/CMSFilter.md index 0349446..e59487f 100644 --- a/docs/WebflowOnly/CMSFilter.md +++ b/docs/WebflowOnly/CMSFilter.md @@ -49,7 +49,7 @@ Add the script to your Webflow project and include the required attributes on yo - `wt-cmsfilter-filtering="advanced"` - Enables advanced filtering mode with dynamic availability updates (every facet’s options narrow to the current result set; selecting one **make** hides other makes). - `wt-cmsfilter-filtering="hybrid"` - Like advanced, but selected categories (see below) keep **all** of their checkbox options that match the current filters **except** that category’s own selections (multi-select friendly). All **other** categories narrow from the current result set like **`advanced`**. -- `wt-cmsfilter-hybrid-categories="bodytype"` - Comma-separated `wt-cmsfilter-category` names that use hybrid self-exclude behavior (e.g. `bodytype` or `bodytype,colour`). **Required** for any facet to use hybrid self-exclude; **omit or leave empty** if every facet should narrow like **`advanced`**. Requires matching `data-*` fields on list items for each listed category. +- `wt-cmsfilter-hybrid-categories="bodytype"` - Comma-separated `wt-cmsfilter-category` names that use hybrid self-exclude behavior (e.g. `bodytype` or `bodytype,colour`). **Required** for any facet to use hybrid self-exclude; **omit or leave empty** if every facet should narrow like **`advanced`**. Requires matching `data-*` fields on list items for each listed category. **Checked** checkbox/radio options in **`hybrid`** stay visible so users can adjust or clear selections when another facet (e.g. make) no longer matches. **`advanced`** does not use this rule. - `wt-cmsfilter-trigger="button"` - Changes filter trigger to button submit instead of real-time - `wt-cmsfilter-class="classname"` - CSS class applied to active filter elements - `wt-cmsfilter-resetix2="true"` - Reset IX2 interactions on filtered items