Reference

MenoFilter API Reference

MenoFilter is a client-side JavaScript library for filtering, sorting, searching, and paginating CMS collection data on static websites. It works with both data attributes (declarative) and a programmatic JavaScript API.


Getting an Instance

MenoFilter instances are registered by collection name. Instances are created automatically when the page loads (from data-meno-filter containers) or can be created programmatically.

// Get an existing instance
const filter = MenoFilter.get('posts');

// Create a new instance
const filter = new MenoFilter({
  collection: 'posts',
  perPage: 10,
  filterMatch: 'and'
});

// Initialize (loads data from inline JSON or static file)
await filter.init();

Constructor Options

Option

Type

Default

Description

collection

string

(required)

Collection name

perPage

number

0 (no pagination)

Items per page

filterMatch

`"and" \

"or"`

"and"

How multiple filter fields combine

fieldTypes

Record<string, FieldType>

{}

Type hints for value coercion

urlSync

boolean

false

Sync filter state to URL query params

urlMode

`"push" \

"replace"`

"replace"

URL update mode (push adds history entries)

fuzzySearch

boolean

false

Enable fuzzy text matching

fuzzyThreshold

number

0.3

Fuzzy match threshold (0-1, lower is stricter)

Static Methods

Method

Returns

Description

MenoFilter.get(collection)

`MenoFilter \

undefined`

Get instance by collection name

MenoFilter.getAll()

Map<string, MenoFilter>

Get all registered instances

MenoFilter.has(collection)

boolean

Check if an instance exists

MenoFilter.destroy(collection)

void

Destroy and unregister an instance

MenoFilter.destroyAll()

void

Destroy all instances


Filtering Methods

Method

Returns

Description

filter(criteria)

CMSItem[]

Apply filter criteria (AND logic between fields)

filterOr(criteriaList)

CMSItem[]

Apply OR logic between criteria objects

addFilter(field, value)

CMSItem[]

Add/update a single filter (merges with existing)

removeFilter(field)

CMSItem[]

Remove filter for a specific field

clearFilters()

CMSItem[]

Clear all filters (keeps sort and search)

getFilters()

FilterCriteria

Get current filter criteria

filterRange(field, { min, max })

CMSItem[]

Apply a range filter (uses $gte/$lte)

clearRangeFilter(field)

CMSItem[]

Clear a range filter

Filter Examples

Simple equality:

filter.filter({ category: 'tech' });

Multiple conditions (AND):

filter.filter({
  category: 'tech',
  published: true
});

With operators:

filter.filter({
  price: { $gt: 100, $lt: 500 },
  tags: { $contains: 'featured' }
});

OR filtering:

filter.filterOr([
  { category: 'tech' },
  { category: 'design' }
]);

Range filter:

filter.filterRange('price', { min: 100, max: 500 });
filter.filterRange('date', { min: '2024-01-01' });

Filter Operators

Operator

Description

Value Type

$eq

Equal to

any

$neq

Not equal to

any

$gt

Greater than

`number \

string`

$gte

Greater than or equal

`number \

string`

$lt

Less than

`number \

string`

$lte

Less than or equal

`number \

string`

$contains

String contains (case-insensitive) or array includes

string

$notContains

String does not contain or array excludes

string

$startsWith

String starts with (case-insensitive)

string

$endsWith

String ends with (case-insensitive)

string

$in

Value is in the given array

any[]

$nin

Value is not in the given array

any[]

$empty

Is empty/null (true) or is not empty (false)

boolean

A filter value of "*", "", null, or undefined is treated as "show all" and skipped.


Search Methods

Method

Returns

Description

search(query, fields?)

CMSItem[]

Search text across fields (case-insensitive)

clearSearch()

CMSItem[]

Clear search query

getSearch()

{ query, fields }

Get current search state

setFuzzySearch(enabled, threshold?)

void

Enable/disable fuzzy matching

isFuzzySearchEnabled()

boolean

Check if fuzzy search is on

// Search all string fields
filter.search('react tutorial');

// Search specific fields only
filter.search('react', ['title', 'tags']);

// Enable fuzzy matching
filter.setFuzzySearch(true, 0.3);
filter.search('reckt'); // matches "react" with typo tolerance

Sort Methods

Method

Returns

Description

sort(field, order?)

CMSItem[]

Sort by field ("asc" or "desc", default "asc")

clearSort()

CMSItem[]

Clear sorting

getSort()

`SortConfig \

null`

Get current sort configuration

filter.sort('publishedAt', 'desc');
filter.sort('title', 'asc');
filter.clearSort();

Pagination Methods

Method

Returns

Description

setPage(n)

CMSItem[]

Go to page number

nextPage()

CMSItem[]

Go to next page

prevPage()

CMSItem[]

Go to previous page

setPerPage(n)

CMSItem[]

Set items per page

getPageInfo()

PageInfo

Get pagination state

PageInfo Object

Field

Type

Description

current

number

Current page number (1-based)

total

number

Total number of pages

hasNext

boolean

Whether there is a next page

hasPrev

boolean

Whether there is a previous page

totalItems

number

Total filtered item count

perPage

number

Items per page

filter.setPerPage(12);
filter.setPage(2);

const info = filter.getPageInfo();
// { current: 2, total: 5, hasNext: true, hasPrev: true, totalItems: 58, perPage: 12 }

Load More Methods

An alternative to pagination where items are appended incrementally.

Method

Returns

Description

loadMore(count?)

CMSItem[]

Load more items (defaults to perPage)

getVisibleItems()

CMSItem[]

Get currently visible items

getLoadMoreInfo()

LoadMoreInfo

Get load-more state

initLoadMore(initialCount?)

void

Initialize load-more mode

LoadMoreInfo Object

Field

Type

Description

visible

number

Number of currently visible items

total

number

Total filtered item count

remaining

number

Items not yet shown

hasMore

boolean

Whether more items can be loaded

filter.initLoadMore(6);
filter.loadMore();     // shows 6 more
filter.loadMore(3);    // shows 3 more

const info = filter.getLoadMoreInfo();
// { visible: 15, total: 50, remaining: 35, hasMore: true }

Data Access Methods

Method

Returns

Description

getAll()

CMSItem[]

All items (unfiltered, unsorted)

getFiltered()

CMSItem[]

Filtered items (before pagination)

getItems()

CMSItem[]

Current page items

getById(id)

`CMSItem \

undefined`

Find item by _id or _filename

getUniqueValues(field)

unknown[]

All unique values for a field

getFacets(field)

FacetCounts

Value counts from filtered items

getAllFacets(field)

FacetCounts

Value counts from all items

getState()

FilterState

Full state snapshot

const allItems = filter.getAll();
const filtered = filter.getFiltered();
const pageItems = filter.getItems();

const categories = filter.getUniqueValues('category');
// ['tech', 'design', 'marketing']

const facets = filter.getFacets('category');
// { tech: 12, design: 8, marketing: 3 }

Reset

Method

Returns

Description

reset()

CMSItem[]

Reset all filters, search, sort, and pagination


Events

Subscribe to lifecycle events using on(). Returns an unsubscribe function.

const unsubscribe = filter.on('afterFilter', (items) => {
  console.log('Filtered to', items.length, 'items');
});

// Later: unsubscribe
unsubscribe();

Event Types

Event

Callback Data

Description

init

CMSItem[]

Fired after data is loaded

beforeFilter

FilterCriteria

Before filter criteria are applied

afterFilter

CMSItem[]

After filtering completes

beforeSort

SortConfig

Before sort is applied

afterSort

CMSItem[]

After sorting completes

beforeSearch

{ query, fields }

Before search is applied

afterSearch

CMSItem[]

After search completes

beforeRender

varies

Before DOM render

afterRender

varies

After DOM render

pageChange

PageInfo

When page changes

loadMore

LoadMoreInfo

When more items are loaded

reset

null

When reset() is called

Watch and Subscribe

// Watch full state changes
const unwatch = filter.watch((state) => {
  console.log(state.pageItems.length, 'items on page', state.page.current);
});

// Subscribe to items only (simplified)
const unsub = filter.subscribe((items) => {
  console.log(items.length, 'current items');
});

URL Sync

Synchronize filter state with URL query parameters so users can share filtered views.

filter.enableUrlSync({ mode: 'push' }); // adds browser history entries
filter.enableUrlSync();                  // replaces URL without history
filter.disableUrlSync();

URL parameter format:

  • Filters: ?filter.category=tech&filter.price.$gt=100

  • Sort: ?sort=publishedAt:desc

  • Search: ?search=react&search.fields=title,tags

  • Page: ?page=2&perPage=12


Data Attributes Reference

Use these HTML attributes for declarative (no-code) filtering.

Container Attributes

Attribute

Description

data-meno-filter="collection"

Root filter container. Value is the collection name.

data-meno-list

Marks the element containing list items

data-meno-per-page="n"

Items per page

`data-meno-filter-match="and\

or"`

How multiple filters combine

data-meno-debounce="ms"

Debounce delay for inputs

data-meno-active-class="className"

Class added to active filter buttons

data-meno-types='{"field":"number"}'

JSON object of field type hints

data-meno-url-sync

Enable URL query parameter sync

Filter Controls

Attribute

Description

data-meno-filter-field="field"

Field name this control filters on

data-meno-filter-value="value"

Value to filter by (on buttons/links)

`data-meno-filter-mode="single\

multi"`

Single or multi-select mode

data-meno-clear

Clears all filters when clicked

data-meno-reset

Resets all state (filters, sort, search, page)

Range Controls

Attribute

Description

data-meno-range="field"

Marks a range filter container

`data-meno-range-bound="min\

max"`

Marks an input as min or max bound

Search Controls

Attribute

Description

data-meno-search

Marks a search input

data-meno-search-fields="field1,field2"

Comma-separated fields to search

data-meno-search-fuzzy

Enable fuzzy matching

data-meno-search-threshold="0.3"

Fuzzy match threshold

Sort Controls

Attribute

Description

data-meno-sort="field"

Sort by this field when clicked

`data-meno-sort-order="asc\

desc"`

Sort direction

Pagination Controls

Attribute

Description

`data-meno-page="prev\

next\

n"`

Page navigation button

data-meno-page-current

Displays the current page number

data-meno-page-total

Displays the total page count

data-meno-page-buttons

Container for auto-generated page buttons

data-meno-per-page-select

Select/input to change items per page

Load More Controls

Attribute

Description

data-meno-load-more

"Load more" button

data-meno-remaining

Displays the remaining item count

Display Elements

Attribute

Description

`data-meno-count="results\

total"`

Shows filtered or total item count

data-meno-facet="field"

Shows facet counts for a field

data-meno-empty

Shown when no items match filters


Declarative Example

<div data-meno-filter="posts" data-meno-per-page="6">
  <!-- Search -->
  <input data-meno-search data-meno-search-fields="title,excerpt" placeholder="Search...">

  <!-- Filter buttons -->
  <button data-meno-filter-field="category" data-meno-filter-value="*">All</button>
  <button data-meno-filter-field="category" data-meno-filter-value="tech">Tech</button>
  <button data-meno-filter-field="category" data-meno-filter-value="design">Design</button>

  <!-- Sort -->
  <button data-meno-sort="publishedAt" data-meno-sort-order="desc">Newest</button>
  <button data-meno-sort="title" data-meno-sort-order="asc">A-Z</button>

  <!-- Results count -->
  <span data-meno-count="results"></span> results

  <!-- Item list -->
  <div data-meno-list>
    <!-- Items are rendered here -->
  </div>

  <!-- Empty state -->
  <div data-meno-empty>No posts found.</div>

  <!-- Pagination -->
  <button data-meno-page="prev">Previous</button>
  <span data-meno-page-current></span> / <span data-meno-page-total></span>
  <button data-meno-page="next">Next</button>
</div>

Next Steps

Building the future of digital experiences, one website at a time

© 2026 Company. All rights reserved.