Utils (@pim.sk/utils)

filter-menu

Live search/filter for navigation <li> lists. Reads text from <a> tags (including <small>), normalizes diacritics, supports nested menus and debounced input.
import filterMenu from '@pim.sk/utils/filter-menu.mjs'

Usage

filterMenu({ input, selector })

Filter <li> items using a CSS selector. Text is read from the <a> tag — including nested <small> — and is diacritics-normalized automatically.

filterMenu({
    input:    inputEl,              // HTMLInputElement
    selector: 'ul.menu-list li',  // CSS selector for <li> items
})
import filterMenu from '@pim.sk/utils/filter-menu.mjs'

const input = document.querySelector('input[type="search"]')
filterMenu({ input, selector: 'ul.menu-list li' })

data-filter-menu (auto-init)

Zero-JS approach — on import, the module auto-initializes every <input type="search"> carrying a data-filter-menu attribute. The attribute value is the CSS selector for the <li> items.

<input type="search"
    data-filter-menu="ul.menu-list li"
    placeholder="Filter..." />

<!-- no JavaScript needed — import is enough -->
import '@pim.sk/utils/filter-menu.mjs'
// auto-init finds all [data-filter-menu] inputs on import — no extra code

Nested <li> — parent visibility

When a child <li> matches the query, its parent <li> stays visible even if the parent text does not match. The selector must cover all levels.

// selector must include ALL li levels (parent + child)
filterMenu({ input, selector: 'ul.menu-list li' })

// "catalog"  → parent "Products" stays visible
// "archive"  → parent "Orders"   stays visible
// "orders"   → "Orders" + all its children
filterMenu({
    input,
    selector: 'ul.menu-list li',  // both parent and child li
})

filterMenu({ input, items })

Pass a NodeList or Array of <li> elements directly — useful when items are already collected or managed by a component.

const liEls = document.querySelectorAll("ul li")

filterMenu({
    input,
    items: liEls,   // NodeList or Array
})
const liEls = document.querySelectorAll("ul li")
filterMenu({ input, items: liEls })

debounceWait

Delay in ms after the last keystroke before filtering runs. Default is 250ms — good for most cases. Set to 0 for instant filtering when items are few or rendering is cheap.

debounceWait: 250   // default
debounceWait: 0     // instant — no delay
debounceWait: 500   // slower inputs / heavy rendering
filterMenu({
    input,
    selector: 'ul li',
    debounceWait: 0,   // instant
})
v 1.1.2