Now.js Framework Documentation

Now.js Framework Documentation

FilterManager

EN 15 Dec 2025 06:21

FilterManager

Overview

FilterManager is the filtering and sorting management system in Now.js Framework. It supports filtering with multiple criteria and animated transitions.

When to use:

  • Need to filter product lists, articles, galleries
  • Need to sort by various fields
  • Need filter UI with animations
  • Need multi-criteria filtering

Why use it:

  • ✅ Declarative HTML attributes
  • ✅ Multiple filter criteria
  • ✅ Sorting (string, number, date)
  • ✅ Animated transitions (fade, slide, scale)
  • ✅ Works with TemplateManager
  • ✅ Debounced operations
  • ✅ Auto-initialization

Basic Usage

Filter Controls

<!-- Filter buttons -->
<div data-filter-scope="#products" data-filter-attr="data-category">
  <button data-filter-value="*" class="active">All</button>
  <button data-filter-value="electronics">Electronics</button>
  <button data-filter-value="clothing">Clothing</button>
  <button data-filter-value="books">Books</button>
</div>

<!-- Filterable items -->
<div id="products" class="product-grid">
  <div class="product" data-category="electronics">
    <h3>iPhone 15</h3>
    <p>$999</p>
  </div>
  <div class="product" data-category="clothing">
    <h3>T-Shirt</h3>
    <p>$25</p>
  </div>
  <div class="product" data-category="electronics">
    <h3>MacBook</h3>
    <p>$1,299</p>
  </div>
  <div class="product" data-category="books">
    <h3>JavaScript Guide</h3>
    <p>$35</p>
  </div>
</div>

Sort Controls

<!-- Sort buttons -->
<div data-sort-scope="#products">
  <button data-sort-by="name" data-sort-type="string">Name</button>
  <button data-sort-by="price" data-sort-type="number">Price</button>
  <button data-sort-by="date" data-sort-type="date">Date</button>
</div>

<!-- Sortable items (must have data attributes for sorting) -->
<div id="products">
  <div class="product" data-name="iphone" data-price="999" data-date="2024-01-15">
    ...
  </div>
  <div class="product" data-name="macbook" data-price="1299" data-date="2024-02-01">
    ...
  </div>
</div>

Filter Options

Animation Types

<!-- Fade animation (default) -->
<div data-filter-scope="#gallery"
     data-filter-attr="data-type"
     data-filter-animation="fade"
     data-filter-duration="300">
  <button data-filter-value="*">All</button>
  <button data-filter-value="photo">Photos</button>
  <button data-filter-value="video">Videos</button>
</div>

<!-- Slide animation -->
<div data-filter-scope="#list"
     data-filter-animation="slide"
     data-filter-duration="400">
  ...
</div>

<!-- Scale animation -->
<div data-filter-scope="#items"
     data-filter-animation="scale"
     data-filter-duration="250">
  ...
</div>

<!-- No animation -->
<div data-filter-scope="#items"
     data-filter-animation="none">
  ...
</div>

Custom Filter Attribute

<!-- Filter by status -->
<div data-filter-scope="#orders" data-filter-attr="data-status">
  <button data-filter-value="*">All</button>
  <button data-filter-value="pending">Pending</button>
  <button data-filter-value="completed">Completed</button>
  <button data-filter-value="cancelled">Cancelled</button>
</div>

<div id="orders">
  <div class="order" data-status="pending">Order #001</div>
  <div class="order" data-status="completed">Order #002</div>
</div>

Sort Options

Sort Types

<!-- String sort (default) -->
<button data-sort-by="name" data-sort-type="string">Sort by Name</button>

<!-- Number sort -->
<button data-sort-by="price" data-sort-type="number">Sort by Price</button>

<!-- Date sort -->
<button data-sort-by="created" data-sort-type="date">Sort by Date</button>

Sort Order

<!-- Ascending (default) -->
<button data-sort-by="price" data-sort-order="asc">Low to High</button>

<!-- Descending -->
<button data-sort-by="price" data-sort-order="desc">High to Low</button>

Toggle Sort Order

Clicking the same sort button toggles between asc/desc:

// First click: sort asc
// Second click: sort desc
// Third click: sort asc

JavaScript API

filter(value, scope, options)

Filter items programmatically:

// Filter items
FilterManager.filter('electronics', '#products', {
  attr: 'data-category',
  animation: 'fade',
  duration: 300
});

// Show all
FilterManager.filter('*', '#products', {
  attr: 'data-category'
});

sort(options)

Sort items:

// Sort by price ascending
FilterManager.sort({
  scope: '#products',
  by: 'price',
  order: 'asc',
  type: 'number'
});

// Sort by name descending
FilterManager.sort({
  scope: '#products',
  by: 'name',
  order: 'desc',
  type: 'string'
});

getFilteredItems(scope)

Get filtered items:

const visibleProducts = FilterManager.getFilteredItems('#products');
console.log(`Showing ${visibleProducts.length} products`);

clearFilters(scope)

Clear all filters:

FilterManager.clearFilters('#products');

getActiveFilter(scope)

Get active filter:

const filter = FilterManager.getActiveFilter('#products');
// { value: 'electronics', attr: 'data-category' }

Configuration

// Default config
FilterManager.config = {
  defaultAnimation: 'fade',       // Default animation type
  defaultDuration: 300,           // Animation duration (ms)
  defaultFilterAttr: 'data-category', // Default filter attribute
  debounceDelay: 150,             // Debounce delay (ms)
  debug: false                    // Debug mode
};

API Reference

FilterManager.filter(value, scope, options)

Filter items

Parameter Type Description
value string Value to filter by (* = show all)
scope string CSS selector for container
options.attr string Attribute for filtering
options.animation string 'fade', 'slide', 'scale', 'none'
options.duration number Animation duration (ms)

FilterManager.sort(options)

Sort items

Parameter Type Description
options.scope string CSS selector for container
options.by string Field name for sorting
options.order string 'asc' or 'desc'
options.type string 'string', 'number', 'date'

FilterManager.getFilteredItems(scope)

Get visible items

Parameter Type Description
scope string CSS selector

Returns: Array<HTMLElement> - Visible elements

FilterManager.clearFilters(scope)

Clear filters

Parameter Type Description
scope string CSS selector

FilterManager.clearSorts(scope)

Clear sorts

Parameter Type Description
scope string CSS selector

FilterManager.getActiveFilter(scope)

Get active filter

Returns: Object|undefined - {value, attr}

FilterManager.getActiveSort(scope)

Get active sort

Returns: Object|undefined - {by, order, type}

Real-World Examples

<div class="gallery-controls">
  <!-- Filters -->
  <div data-filter-scope="#gallery" data-filter-attr="data-type">
    <button data-filter-value="*" class="active">All</button>
    <button data-filter-value="photo">Photos</button>
    <button data-filter-value="video">Videos</button>
    <button data-filter-value="document">Documents</button>
  </div>

  <!-- Sort -->
  <div data-sort-scope="#gallery">
    <button data-sort-by="name" data-sort-type="string">Name</button>
    <button data-sort-by="size" data-sort-type="number">Size</button>
    <button data-sort-by="date" data-sort-type="date">Date</button>
  </div>
</div>

<div id="gallery" class="grid">
  <div class="item" data-type="photo" data-name="sunset" data-size="2048" data-date="2024-01-15">
    <img src="/photos/sunset.jpg" alt="Sunset">
    <span>sunset.jpg (2 MB)</span>
  </div>
  <div class="item" data-type="video" data-name="tutorial" data-size="50000" data-date="2024-02-01">
    <video src="/videos/tutorial.mp4"></video>
    <span>tutorial.mp4 (50 MB)</span>
  </div>
  <div class="item" data-type="document" data-name="report" data-size="256" data-date="2024-01-20">
    <img src="/icons/pdf.svg" alt="PDF">
    <span>report.pdf (256 KB)</span>
  </div>
</div>

Dynamic Filtering from API

// Load data and filter
async function loadAndFilter(category) {
  const products = await ApiService.get('/api/products');

  // Render with TemplateManager
  TemplateManager.render({ products }, document.querySelector('#product-list'));

  // Apply filter after render
  setTimeout(() => {
    if (category !== 'all') {
      FilterManager.filter(category, '#product-list', {
        attr: 'data-category',
        animation: 'fade'
      });
    }
  }, 100);
}

Common Pitfalls

⚠️ 1. Must Have data-filter-scope

<!-- ❌ Won't work - no scope -->
<div>
  <button data-filter-value="electronics">Electronics</button>
</div>

<!-- ✅ Must have scope -->
<div data-filter-scope="#products" data-filter-attr="data-category">
  <button data-filter-value="electronics">Electronics</button>
</div>

⚠️ 2. Items Must Have Filter Attribute

<!-- ❌ Won't work - no data-category -->
<div id="products">
  <div class="product">iPhone</div>
</div>

<!-- ✅ Must have attribute -->
<div id="products">
  <div class="product" data-category="electronics">iPhone</div>
</div>

⚠️ 3. Wait for Template Render

// ❌ Filter may not work if template hasn't rendered
TemplateManager.render(data, container);
FilterManager.filter('electronics', '#products', options);

// ✅ Wait for template render first
TemplateManager.render(data, container);
setTimeout(() => {
  FilterManager.filter('electronics', '#products', options);
}, 100);

// ✅ Or use event listener
EventManager.on('template:render', () => {
  FilterManager.filter('electronics', '#products', options);
});