Skip to content

misits/advanced-filter-system

Repository files navigation

Advanced Filter System (AFS)

A powerful and flexible vanilla JavaScript filtering system that provides advanced filtering, searching, sorting, and pagination capabilities for DOM elements. Zero dependencies, lightweight, and highly customizable.

✨ NEW in v1.5.1: Enhanced mixed mode filtering, improved event system, and comprehensive URL state management!

Live Demo | NPM Package | Interactive Examples

Table of Contents

Features

  • 🎯 Advanced Filter Logic
    • Mixed mode (OR within categories, AND between)
    • Per-type logic configuration
    • Multi-select and toggle modes
    • Category-specific clearing
  • 🔍 Multiple Filter Types
    • Button filters (toggle/multi-select)
    • Select dropdowns
    • Radio buttons (exclusive)
    • Checkboxes (multi-select)
    • Range sliders with histograms
    • Date range filters
  • 🔎 Smart Search
    • Real-time fuzzy search
    • Multiple searchable fields
    • Configurable debouncing
    • Minimum character threshold
  • ↕️ Flexible Sorting
    • Multi-column sorting
    • Custom sort functions
    • Auto-detect data types
    • Sort direction indicators
  • 📄 Advanced Pagination
    • Dynamic page sizes
    • Smooth transitions
    • Scroll-to-top option
    • Custom pagination controls
  • 🎨 Rich Animations
    • 14+ animation types (fade, slide, scale, flip, etc.)
    • Hardware-accelerated transitions
    • Customizable duration and easing
  • 🔗 State Management
    • URL state persistence
    • Browser history support
    • Shareable filtered URLs
    • State import/export
  • Performance Optimized
    • Debounced updates
    • Efficient DOM manipulation
    • Minimal reflows and repaints
  • 🎯 Event System
    • Comprehensive event API
    • Custom event support
    • Debug mode with logging

Installation

# NPM
npm install advanced-filter-system

# Yarn
yarn add advanced-filter-system

# PNPM
pnpm add advanced-filter-system

Or include via CDN:

<script type="module">
    import { AFS } from 'https://unpkg.com/advanced-filter-system@latest/dist/afs.modern.js';
</script>

Quick Start

HTML Structure

<!DOCTYPE html>
<html>
<head>
    <title>AFS Demo</title>
</head>
<body>
    <!-- Filter Controls -->
    <div class="filter-controls">
        <button class="btn-filter" data-filter="*">All</button>
        <button class="btn-filter" data-filter="category:tech">Technology</button>
        <button class="btn-filter" data-filter="category:design">Design</button>
    </div>
    
    <!-- Search Input -->
    <input type="text" class="filter-search" placeholder="Search...">
    
    <!-- Results Counter -->
    <div class="filter-counter"></div>
    
    <!-- Filterable Items -->
    <div class="items-container">
        <div class="filter-item" 
             data-categories="category:tech brand:apple" 
             data-title="MacBook Pro"
             data-price="2499"
             data-date="2024-03-15">
            <h3>MacBook Pro</h3>
            <p>$2,499</p>
        </div>
        <!-- More items... -->
    </div>
    
    <!-- Pagination Container -->
    <div class="afs-pagination-container"></div>
</body>
</html>

JavaScript Initialization

import { AFS } from 'advanced-filter-system';

const afs = new AFS({
    // Required selectors
    containerSelector: '.items-container',
    itemSelector: '.filter-item',
    filterButtonSelector: '.btn-filter',
    searchInputSelector: '.filter-search',
    counterSelector: '.filter-counter',
    
    // Search configuration
    searchKeys: ['title', 'categories'],
    
    // NEW: Advanced filter logic
    filterCategoryMode: 'mixed', // OR within categories, AND between
    filterTypeLogic: {
        category: { mode: 'OR', multi: true },  // Multi-select OR
        brand: 'OR',                            // Toggle mode
        price: 'AND'                            // Multi-select AND
    },
    
    // Pagination
    pagination: {
        enabled: true,
        itemsPerPage: 12
    },
    
    // Animations
    animation: {
        type: 'fade',
        duration: 300
    },
    
    // Debug mode
    debug: true
});

Filter Logic Modes

Mixed Mode (Recommended)

The most intuitive filtering experience - OR logic within filter categories, AND logic between different categories.

const afs = new AFS({
    filterCategoryMode: 'mixed',
    // When user selects: Tech OR Design AND Apple OR Samsung
    // Shows: (Tech OR Design) AND (Apple OR Samsung)
});

Per-Type Logic Configuration

Configure each filter type independently for maximum flexibility.

const afs = new AFS({
    filterCategoryMode: 'mixed',
    filterTypeLogic: {
        category: { mode: 'OR', multi: true },  // Multi-select checkboxes
        brand: 'OR',                            // Toggle buttons (exclusive)
        price: 'AND',                           // Multi-select with AND logic
        features: { mode: 'OR', multi: true }   // Multi-select with OR logic
    }
});

// Update logic at runtime
afs.filter.setFilterTypeLogic('brand', { mode: 'OR', multi: true });

Legacy Modes

// Legacy OR mode (all filters use OR logic)
const afs = new AFS({ filterCategoryMode: 'OR' });

// Legacy AND mode (all filters use AND logic)
const afs = new AFS({ filterCategoryMode: 'AND' });

Filter Types & UI Components

Button Filters

<!-- Toggle mode (exclusive) -->
<button class="btn-filter" data-filter="category:tech">Technology</button>

<!-- Multi-select mode -->
<button class="btn-filter" data-filter="brand:apple">Apple</button>
<button class="btn-filter" data-filter="brand:samsung">Samsung</button>

<!-- Clear specific category -->
<button class="btn-filter" data-filter="category:*">Clear Categories</button>

Select Dropdowns

<select class="afs-filter-dropdown">
    <option value="*">All Categories</option>
    <option value="category:tech">Technology</option>
    <option value="category:design">Design</option>
</select>

Radio Buttons

<label><input type="radio" name="category" class="btn-filter" data-filter="*" checked> All</label>
<label><input type="radio" name="category" class="btn-filter" data-filter="category:tech"> Tech</label>
<label><input type="radio" name="category" class="btn-filter" data-filter="category:design"> Design</label>

Checkboxes

<label><input type="checkbox" class="btn-filter" data-filter="category:tech"> Technology</label>
<label><input type="checkbox" class="btn-filter" data-filter="category:design"> Design</label>

Range Sliders

// Add price range slider with histogram
afs.rangeFilter.addRangeSlider({
    key: 'price',
    type: 'number',
    container: '.price-range-container',
    min: 0,
    max: 3000,
    step: 50,
    ui: {
        showHistogram: true,
        bins: 10
    }
});

// Add rating range slider
afs.rangeFilter.addRangeSlider({
    key: 'rating',
    type: 'number',
    container: '.rating-range-container',
    min: 4.0,
    max: 5.0,
    step: 0.1
});

Date Range Filters

// Add date range filter
afs.dateFilter.addDateRange({
    key: 'date',
    container: '.date-range-container',
    minDate: new Date('2024-01-01'),
    maxDate: new Date(),
    format: 'YYYY-MM-DD'
});

Advanced Features

Search & Filtering

// Programmatic search
afs.search.search('query');
afs.search.clearSearch();
afs.search.setValue('new query');

// Programmatic filtering
afs.filter.addFilter('category:tech');
afs.filter.removeFilter('category:tech');
afs.filter.clearAllFilters();
afs.filter.clearFilterCategory('category:*');

Sorting

// Sort by single field
afs.sort.sort('price', 'desc');

// Custom sorting
afs.sort.sortWithComparator('title', (a, b) => {
    return a.localeCompare(b, 'en', { numeric: true });
});

// Shuffle items
afs.sort.shuffle();

Pagination

// Pagination navigation
afs.pagination.goToPage(2);
afs.pagination.nextPage();
afs.pagination.previousPage();

// Toggle pagination mode
afs.pagination.setPaginationMode(true); // Enable
afs.pagination.setPaginationMode(false); // Show all

URL State Management

// Enable URL state persistence
const afs = new AFS({
    preserveState: true,
    urlStateKey: 'filters' // Custom URL parameter name
});

// Manual state management
const state = afs.getState();
afs.setState(state);

Animations

const afs = new AFS({
    animation: {
        type: 'fade', // fade, slide, scale, flip, rotate, zoom, bounce, blur, etc.
        duration: 400,
        easing: 'ease-out'
    }
});

// Change animation options at runtime
afs.updateOptions({
    animation: {
        type: 'slide',
        duration: 400
    }
});

Configuration Options

const afs = new AFS({
    // Required selectors
    containerSelector: '.items-container',
    itemSelector: '.filter-item',
    filterButtonSelector: '.btn-filter',
    searchInputSelector: '.filter-search',
    counterSelector: '.filter-counter',
    
    // Filter logic (NEW!)
    filterCategoryMode: 'mixed', // 'mixed', 'OR', 'AND'
    filterTypeLogic: {
        category: { mode: 'OR', multi: true },
        brand: 'OR',
        price: 'AND'
    },
    
    // Search configuration
    searchKeys: ['title', 'categories', 'description'],
    debounceTime: 300,
    
    // Pagination
    pagination: {
        enabled: true,
        itemsPerPage: 12,
        container: '.afs-pagination-container',
        showPrevNext: true,
        scrollToTop: true,
        scrollBehavior: 'smooth'
    },
    
    // Counter display
    counter: {
        template: 'Showing {visible} of {total}',
        showFiltered: true,
        filteredTemplate: '({filtered} filtered)',
        noResultsTemplate: 'No items found',
        formatter: (num) => num.toLocaleString()
    },
    
    // Animations
    animation: {
        type: 'fade',
        duration: 300,
        easing: 'ease-out'
    },
    
    // State management
    preserveState: true,
    stateExpiry: 86400000, // 24 hours
    observeDOM: false,
    
    // CSS Classes
    activeClass: 'active',
    hiddenClass: 'hidden',
    activeSortClass: 'sort-active',
    
    // Debug mode
    debug: true
});

API Reference

Core Methods

// Filter management
afs.filter.addFilter('category:tech');
afs.filter.removeFilter('category:tech');
afs.filter.clearAllFilters();
afs.filter.clearFilterCategory('category:*');
afs.filter.setFilterTypeLogic('brand', { mode: 'OR', multi: true });
afs.filter.toggleFilterExclusive('category:tech');

// Search
afs.search.search('query');
afs.search.clearSearch();
afs.search.setValue('new query');
const currentQuery = afs.search.getValue();

// Sorting  
afs.sort.sort('price', 'desc');
afs.sort.sortMultiple([
    { key: 'category', direction: 'asc' },
    { key: 'price', direction: 'desc' }
]);
afs.sort.shuffle();
afs.sort.reset();

// Pagination
afs.pagination.goToPage(2);
afs.pagination.nextPage();
afs.pagination.previousPage();
afs.pagination.setPaginationMode(true);

// Range Filters
afs.rangeFilter.addRangeSlider({
    key: 'price',
    container: '.price-range-container'
});

// Date Filters
afs.dateFilter.addDateRange({
    key: 'date',
    container: '.date-range-container'
});

// State
const state = afs.getState();
afs.setState(state);

// Events
afs.on('filtersApplied', (data) => {
    console.log(`Showing ${data.visibleItems} of ${data.total} items`);
});

Event System

// Available events
afs.on('filtersApplied', callback);
afs.on('search', callback);
afs.on('sort', callback);
afs.on('pageChanged', callback);
afs.on('urlStateLoaded', callback);

Examples

The project includes comprehensive examples demonstrating all features:

Running Examples Locally

# Clone the repository
git clone https://github.com/misits/advanced-filter-system.git
cd advanced-filter-system

# Open examples in browser
open examples/index.html

Browser Support

  • Chrome (latest)
  • Firefox (latest)
  • Safari (latest)
  • Edge (latest)
  • Opera (latest)

Modern browser features used:

  • ES6 Modules
  • CSS Custom Properties
  • IntersectionObserver API
  • URLSearchParams API

TypeScript Support

Full TypeScript support with comprehensive type definitions:

import { AFS, AFSOptions, FilterTypeLogic } from 'advanced-filter-system';

interface CustomOptions extends AFSOptions {
    customProperty: string;
}

const filterLogic: FilterTypeLogic = {
    category: { mode: 'OR', multi: true },
    brand: 'OR'
};

const afs = new AFS({
    containerSelector: '#items',
    itemSelector: '.item',
    filterTypeLogic: filterLogic
} as CustomOptions);

Contributing

We welcome contributions! Please see our Contributing Guide for details on:

  1. Setting up the development environment
  2. Code style and standards
  3. Testing requirements
  4. Pull request process
  5. Bug reporting guidelines
  6. Feature request templates

Development Setup

# Clone and install
git clone https://github.com/misits/advanced-filter-system.git
cd advanced-filter-system
npm install

# Run development server
npm run dev

# Build for production
npm run build

# Run tests
npm test

License

This project is licensed under the MIT License - see the LICENSE file for details.


Made with ♥ by misits

Star ⭐ this repo if you find it helpful!

About

A flexible and powerful JavaScript library for filtering DOM elements with search and sorting functionality.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Sponsor this project

Packages