SmartFilter.js
Find What You Need, Instantly!
SmartFilter.js is a powerful JavaScript library that provides advanced filtering capabilities for lists, navigation menus, and other DOM elements. It features fuzzy search with intelligent scoring, performance optimizations, and a robust error handling system.
Installation
Include the SmartFilter.js script in your HTML file:
<script src="path/to/smartFilter.js"></script>
Basic initialization
// Initialize with default options
var filter = new ListFilter('#navigation-list', '#search-input');
// Or with custom options
var filter = new ListFilter('#navigation-list', '#search-input', {
debounceWait: 300,
minLength: 2,
caseSensitive: false,
onFilter: function(value) {
console.log('Filtering with:', value);
}
});
HTML Structure
<input type="text" id="search-input" placeholder="Search...">
<span class="js-filter-message"></span>
<nav id="navigation-list">
<ul>
<li class="nav-title">Category 1</li>
<li>
<a href="page1.html">
<span class="nav-link-text">Page 1</span>
</a>
</li>
<li>
<a href="page2.html">
<span class="nav-link-text">Page 2</span>
</a>
</li>
<li class="nav-title">Category 2</li>
<li>
<a href="page3.html">
<span class="nav-link-text">Page 3</span>
</a>
</li>
</ul>
</nav>
<span class="nav-link-text">
element containing the text to be filtered.
Configuration Options
SmartFilter.js offers several configuration options to customize its behavior:
Option | Default Value | Description | Type |
---|---|---|---|
anchor |
null | Element to which the filter class will be applied (instead of the list element). | Element|string|null |
messageSelector |
'.js-filter-message' | Selector for the element that displays the match count. | string |
debounceWait |
250 | Time in milliseconds to wait before filtering after input changes. | number |
minLength |
1 | Minimum number of characters required to trigger filtering. | number |
maxLength |
100 | Maximum number of characters allowed in the search input. | number |
caseSensitive |
false | Whether the filter should be case-sensitive. | boolean |
onFilter |
null | Callback function that is called when filtering occurs. | Function|null |
onReset |
null | Callback function that is called when the filter is reset. | Function|null |
onError |
null | Callback function that is called when an error occurs. | Function|null |
Advanced Configuration Example
Here's an example of how to configure SmartFilter with advanced options:
var filter = new ListFilter('#navigation-list', '#search-input', {
anchor: '#nav-container',
messageSelector: '.filter-results',
debounceWait: 300,
minLength: 2,
maxLength: 50,
caseSensitive: false,
onFilter: function(value) {
console.log('Filtering with:', value);
// Update UI or trigger other actions
},
onReset: function() {
console.log('Filter has been reset');
// Restore original state or trigger other actions
},
onError: function(error) {
console.error('Filter error:', error);
// Handle errors gracefully
}
});
Fuzzy Search Algorithm
SmartFilter.js uses an advanced fuzzy search algorithm with intelligent scoring:
// Match weights used by the fuzzy search algorithm
var MATCH_WEIGHTS = {
EXACT: 3, // Exact match gets highest score
SUBSTRING: 2, // Substring match gets second highest score
CONSECUTIVE: 0.5, // Consecutive character matches
CONSECUTIVE_BONUS: 0.1, // Bonus for each additional consecutive match
NON_CONSECUTIVE: 0.3, // Non-consecutive character matches
PREFIX_BONUS: 0.2, // Bonus for matching at the beginning
CASE_MATCH_BONUS: 0.1 // Bonus for matching case
};
The algorithm provides several advantages:
- Typo tolerance: Finds matches even when users make typing errors
- Partial matching: Works with incomplete search terms
- Intelligent scoring: Ranks results by relevance
- Performance optimization: Uses caching to improve speed
- Case sensitivity options: Can match exact case or ignore case
Performance Optimizations
SmartFilter.js includes several performance optimizations:
Debouncing
// Debounce function with rate limiting
function debounce(func, wait, immediate) {
var timeout;
var lastRun = 0;
return function() {
var context = this;
var args = arguments;
var now = Date.now();
// Rate limiting
if (now - lastRun < RATE_LIMIT_MS) {
return;
}
// Debounce implementation
clearTimeout(timeout);
timeout = setTimeout(function() {
timeout = null;
if (!immediate) func.apply(context, args);
}, wait);
if (immediate && !timeout) func.apply(context, args);
};
}
Result Caching
// Cache for fuzzy match results
var fuzzyMatchCache = new Map();
// Check cache before computing match
var cacheKey = pattern + '|' + str;
if (fuzzyMatchCache.has(cacheKey)) {
return fuzzyMatchCache.get(cacheKey);
}
// Store result in cache
fuzzyMatchCache.set(cacheKey, score);
DOM Caching
// Pre-cache DOM elements
this._cache = {
items: this.list.getElementsByTagName('a'),
titles: this.list.getElementsByTagName('li'),
messageElement: document.querySelector(this.settings.messageSelector),
size: 0
};
API Methods
SmartFilter.js exposes several methods for programmatic control:
// Get filter instance
var filter = new ListFilter('#navigation-list', '#search-input');
// Manually trigger filtering
filter.filter();
// Reset the filter (clear input and show all items)
filter.reset();
// Destroy the filter instance and clean up
filter.destroy();
Internal Methods
// Find the navigation title associated with an element
filter.findNavTitle(element);
// Show all parent elements of a given element
filter.showParents(element);
// Show all child elements of a given element
filter.showChildren(element);
Error Handling
SmartFilter.js includes a robust error handling system:
// Error handling with auto-recovery
_handleError: function(error) {
console.error('ListFilter error:', error);
// Track error frequency
var now = Date.now();
if (now - this._lastErrorTime > 60000) {
this._errorCount = 0;
}
this._errorCount++;
this._lastErrorTime = now;
// Call error callback if provided
if (this.settings.onError) {
this.settings.onError(error);
}
// Auto-recovery if too many errors
if (this._errorCount > 10) {
this.reset();
this._errorCount = 0;
}
}
The error handling system provides:
- Detailed error logging: Logs errors with context information
- Error rate tracking: Monitors error frequency
- Custom error callbacks: Allows custom error handling
- Auto-recovery: Automatically resets the filter if too many errors occur
- Input validation: Prevents common errors by validating inputs
Event Handling
SmartFilter.js uses efficient event handling to manage user interactions:
// Bind events with passive listeners for better performance
bindEvents: function() {
var self = this;
this.handleFilter = debounce(this.filter.bind(this), this.settings.debounceWait);
// Use passive event listeners for better performance
this.input.addEventListener('input', this._validateEvent.bind(this), { passive: true });
this.input.addEventListener('change', this._validateEvent.bind(this), { passive: true });
// Add ESC key handler
document.addEventListener('keydown', function(e) {
if (e.key === 'Escape' || e.key === 'Esc') {
self.reset();
}
});
// Handle window resize for responsive layouts
this._resizeHandler = debounce(function() {
if (self.input.value.length > self.settings.minLength) {
self.filter();
}
}, 250);
window.addEventListener('resize', this._resizeHandler, { passive: true });
}
The filter responds to the following events:
- input: Triggers filtering when the search input changes
- change: Triggers filtering when the search input loses focus
- keydown (Escape): Resets the filter when the Escape key is pressed
- resize: Re-applies the filter when the window is resized
- click: Resets the filter when the message element is clicked
CSS Classes
SmartFilter.js uses several CSS classes to manage the visibility of elements:
Class | Description | Applied To |
---|---|---|
js-list-filter |
Indicates that the element is a filterable list | List element or anchor element |
js-list-active |
Indicates that the filter is currently active | List element |
js-filter-hide |
Hides elements that don't match the filter | List items |
js-filter-show |
Shows elements that match the filter | List items |
nav-title |
Identifies category titles in the navigation | Category title elements |
nav-link-text |
Identifies the text content to be filtered | Text elements inside links |
Best Practices
- Set an appropriate
debounceWait
value (200-300ms is recommended) to balance responsiveness and performance - Use the
minLength
option to prevent filtering on very short inputs - Provide a clear visual indication when filtering is active
- Include a way for users to clear the filter (the filter automatically supports the Escape key)
- Use the
onFilter
andonReset
callbacks to synchronize other UI elements - Implement proper error handling with the
onError
callback
debounceWait
value to reduce the frequency of filtering operations and improve performance.
Troubleshooting
- Filter not working? Check that your HTML structure includes
<span class="nav-link-text">
elements inside your links. - No matches found? Verify that the text content of your items matches what users are searching for.
- Performance issues? Try increasing the
debounceWait
value and ensure you're not filtering extremely large lists. - Filter showing incorrect results? Check that your navigation titles are properly marked with the
nav-title
class. - Match count not showing? Verify that you have an element matching the
messageSelector
option.