Skip to content

Commit 5a1ad78

Browse files
author
matthewcsimpson
committed
hybrid filtering update
1 parent 9251da0 commit 5a1ad78

3 files changed

Lines changed: 57 additions & 11 deletions

File tree

Dist/WebflowOnly/CMSFilter.js

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,6 @@
11
"use strict";
22

33
class CMSFilter {
4-
/**
5-
* For `wt-cmsfilter-filtering="hybrid"`, availability for these categories ignores
6-
* that category's active filters (e.g. body type options stay available for multi-select
7-
* while other facets narrow from the full filtered set).
8-
*/
9-
static HYBRID_SELF_EXCLUDE_CATEGORIES = ["bodytype"];
10-
114
constructor() {
125
//CORE elements
136
this.filterForm = document.querySelector(
@@ -784,6 +777,25 @@ class CMSFilter {
784777
});
785778
}
786779

780+
/**
781+
* Categories whose checkbox availability ignores that facet’s own selections (hybrid mode).
782+
* Set on the form: wt-cmsfilter-hybrid-categories="bodytype" or "bodytype,colour"
783+
* If the attribute is omitted, defaults to ["bodytype"]. If present but empty, no categories self-exclude.
784+
*/
785+
getHybridSelfExcludeCategories() {
786+
const raw = this.filterForm.getAttribute(
787+
"wt-cmsfilter-hybrid-categories",
788+
);
789+
if (raw === null) {
790+
return ["bodytype"];
791+
}
792+
const parsed = raw
793+
.split(",")
794+
.map((s) => s.trim())
795+
.filter(Boolean);
796+
return parsed;
797+
}
798+
787799
UpdateAvailableFilters() {
788800
const filteringMode = this.filterForm.getAttribute(
789801
"wt-cmsfilter-filtering",
@@ -800,7 +812,7 @@ class CMSFilter {
800812
if (
801813
filteringMode === "hybrid" &&
802814
categoryAttr &&
803-
CMSFilter.HYBRID_SELF_EXCLUDE_CATEGORIES.includes(categoryAttr)
815+
this.getHybridSelfExcludeCategories().includes(categoryAttr)
804816
) {
805817
sourceItems = this.getFilteredItemsIgnoringCategories([categoryAttr]);
806818
}

__tests__/CMSFilter.test.js

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,12 +74,19 @@ describe("CMSFilter", () => {
7474
}
7575

7676
/** make, bodytype, Category — hybrid (bodytype self-exclude) vs advanced */
77-
function buildHybridScenarioDOM(filteringMode = "hybrid") {
77+
function buildHybridScenarioDOM(
78+
filteringMode = "hybrid",
79+
hybridCategoriesAttr,
80+
) {
7881
const modeAttr = filteringMode
7982
? `wt-cmsfilter-filtering="${filteringMode}"`
8083
: "";
84+
const hybridAttr =
85+
hybridCategoriesAttr !== undefined
86+
? `wt-cmsfilter-hybrid-categories="${hybridCategoriesAttr}"`
87+
: "";
8188
document.body.innerHTML = `
82-
<form wt-cmsfilter-element="filter-form" ${modeAttr} wt-cmsfilter-debounce="0">
89+
<form wt-cmsfilter-element="filter-form" ${modeAttr} ${hybridAttr} wt-cmsfilter-debounce="0">
8390
<label wt-cmsfilter-category="make"><input type="checkbox"><span>Toyota</span></label>
8491
<label wt-cmsfilter-category="make"><input type="checkbox"><span>Honda</span></label>
8592
<label wt-cmsfilter-category="bodytype"><input type="checkbox"><span>SUV</span></label>
@@ -235,6 +242,32 @@ describe("CMSFilter", () => {
235242
]);
236243
});
237244

245+
test("hybrid with empty wt-cmsfilter-hybrid-categories narrows all facets like advanced", () => {
246+
buildHybridScenarioDOM("hybrid", "");
247+
InitializeCMSFilter();
248+
const form = document.querySelector('[wt-cmsfilter-element="filter-form"]');
249+
const toyota = Array.from(
250+
form.querySelectorAll('label[wt-cmsfilter-category="make"]'),
251+
).find((l) => l.textContent.includes("Toyota"));
252+
const suv = Array.from(
253+
form.querySelectorAll('label[wt-cmsfilter-category="bodytype"]'),
254+
).find((l) => l.textContent.includes("SUV"));
255+
toyota.querySelector("input").checked = true;
256+
suv.querySelector("input").checked = true;
257+
toyota
258+
.querySelector("input")
259+
.dispatchEvent(new Event("change", { bubbles: true }));
260+
suv.querySelector("input").dispatchEvent(new Event("change", { bubbles: true }));
261+
const instance = window.webtricks[0].CMSFilter;
262+
instance.ApplyFilters();
263+
264+
const bodyLabels = Array.from(
265+
form.querySelectorAll('label[wt-cmsfilter-category="bodytype"]'),
266+
);
267+
const visibleBody = bodyLabels.filter((l) => l.style.display !== "none");
268+
expect(visibleBody.map((l) => l.textContent.trim())).toEqual(["SUV"]);
269+
});
270+
238271
test("advanced mode hides sibling make and hides body types not in result set", () => {
239272
buildHybridScenarioDOM("advanced");
240273
InitializeCMSFilter();

docs/WebflowOnly/CMSFilter.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,8 @@ Add the script to your Webflow project and include the required attributes on yo
4848
#### Core Filter Attributes
4949

5050
- `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).
51-
- `wt-cmsfilter-filtering="hybrid"` - Like advanced, but **`bodytype`** keeps **all** of its checkbox options that match the current filters **except** body type (so users can multi-select e.g. Minivan and SUV while other facets react). **`make`** and all other categories narrow from the current result set like **`advanced`**. Requires matching `data-bodytype` on list items (`wt-cmsfilter-category="bodytype"`).
51+
- `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`**.
52+
- `wt-cmsfilter-hybrid-categories="bodytype"` - Comma-separated `wt-cmsfilter-category` names that use hybrid self-exclude behavior (e.g. `bodytype` or `bodytype,colour`). **If omitted**, defaults to **`bodytype`**. **If present but empty**, every facet narrows like **`advanced`** (no hybrid self-exclude). Requires matching `data-*` fields on list items for each listed category.
5253
- `wt-cmsfilter-trigger="button"` - Changes filter trigger to button submit instead of real-time
5354
- `wt-cmsfilter-class="classname"` - CSS class applied to active filter elements
5455
- `wt-cmsfilter-resetix2="true"` - Reset IX2 interactions on filtered items

0 commit comments

Comments
 (0)