Now.js Framework Documentation

Now.js Framework Documentation

FilterManager

TH 15 Dec 2025 08:52

FilterManager

ภาพรวม

FilterManager คือระบบจัดการ filtering และ sorting ของ items ใน Now.js Framework รองรับการกรองด้วยหลายเกณฑ์ พร้อม animated transitions

ใช้เมื่อ:

  • ต้องการกรองรายการสินค้า, บทความ, gallery
  • ต้องการ sorting ตาม field ต่างๆ
  • ต้องการ filter UI พร้อม animations
  • ต้องการ multi-criteria filtering

ทำไมต้องใช้:

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

การใช้งานพื้นฐาน

Filter Controls

<!-- Filter buttons -->
<div data-filter-scope="#products" data-filter-attr="data-category">
  <button data-filter-value="*" class="active">ทั้งหมด</button>
  <button data-filter-value="electronics">อิเล็กทรอนิกส์</button>
  <button data-filter-value="clothing">เสื้อผ้า</button>
  <button data-filter-value="books">หนังสือ</button>
</div>

<!-- Filterable items -->
<div id="products" class="product-grid">
  <div class="product" data-category="electronics">
    <h3>iPhone 15</h3>
    <p>฿35,000</p>
  </div>
  <div class="product" data-category="clothing">
    <h3>T-Shirt</h3>
    <p>฿500</p>
  </div>
  <div class="product" data-category="electronics">
    <h3>MacBook</h3>
    <p>฿55,000</p>
  </div>
  <div class="product" data-category="books">
    <h3>JavaScript Guide</h3>
    <p>฿450</p>
  </div>
</div>

Sort Controls

<!-- Sort buttons -->
<div data-sort-scope="#products">
  <button data-sort-by="name" data-sort-type="string">ชื่อ</button>
  <button data-sort-by="price" data-sort-type="number">ราคา</button>
  <button data-sort-by="date" data-sort-type="date">วันที่</button>
</div>

<!-- Sortable items (ต้องมี data attributes สำหรับ sort) -->
<div id="products">
  <div class="product" data-name="iphone" data-price="35000" data-date="2024-01-15">
    ...
  </div>
  <div class="product" data-name="macbook" data-price="55000" 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="*">ทั้งหมด</button>
  <button data-filter-value="pending">รอดำเนินการ</button>
  <button data-filter-value="completed">เสร็จสิ้น</button>
  <button data-filter-value="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

เมื่อคลิกปุ่ม sort เดิมซ้ำ จะ toggle ระหว่าง asc/desc:

// คลิกครั้งแรก: เรียง asc
// คลิกครั้งสอง: เรียง desc
// คลิกครั้งสาม: เรียง asc

JavaScript API

filter(value, scope, options)

กรอง items ด้วย JavaScript:

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

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

sort(options)

เรียง 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)

รับ items ที่ถูกกรองแล้ว:

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

clearFilters(scope)

ล้าง filters ทั้งหมด:

FilterManager.clearFilters('#products');

getActiveFilter(scope)

รับ filter ที่ active อยู่:

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

การตั้งค่า

// 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 อ้างอิง

FilterManager.filter(value, scope, options)

กรอง items

Parameter Type Description
value string ค่าที่จะกรอง (* = แสดงทั้งหมด)
scope string CSS selector ของ container
options.attr string Attribute สำหรับกรอง
options.animation string 'fade', 'slide', 'scale', 'none'
options.duration number Animation duration (ms)

FilterManager.sort(options)

เรียง items

Parameter Type Description
options.scope string CSS selector ของ container
options.by string Field name สำหรับ sort
options.order string 'asc' หรือ 'desc'
options.type string 'string', 'number', 'date'

FilterManager.getFilteredItems(scope)

รับ visible items

Parameter Type Description
scope string CSS selector

Returns: Array<HTMLElement> - Visible elements

FilterManager.clearFilters(scope)

ล้าง filters

Parameter Type Description
scope string CSS selector

FilterManager.clearSorts(scope)

ล้าง sorts

Parameter Type Description
scope string CSS selector

FilterManager.getActiveFilter(scope)

รับ active filter

Returns: Object|undefined - {value, attr}

FilterManager.getActiveSort(scope)

รับ active sort

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

ตัวอย่างการใช้งานจริง

<div class="gallery-controls">
  <!-- Filters -->
  <div data-filter-scope="#gallery" data-filter-attr="data-type">
    <button data-filter-value="*" class="active">ทั้งหมด</button>
    <button data-filter-value="photo">รูปภาพ</button>
    <button data-filter-value="video">วิดีโอ</button>
    <button data-filter-value="document">เอกสาร</button>
  </div>

  <!-- Sort -->
  <div data-sort-scope="#gallery">
    <button data-sort-by="name" data-sort-type="string">ชื่อ</button>
    <button data-sort-by="size" data-sort-type="number">ขนาด</button>
    <button data-sort-by="date" data-sort-type="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);
}

ข้อควรระวัง

⚠️ 1. ต้องมี data-filter-scope

<!-- ❌ ไม่ work - ไม่มี scope -->
<div>
  <button data-filter-value="electronics">Electronics</button>
</div>

<!-- ✅ ต้องมี scope -->
<div data-filter-scope="#products" data-filter-attr="data-category">
  <button data-filter-value="electronics">Electronics</button>
</div>

⚠️ 2. Items ต้องมี filter attribute

<!-- ❌ ไม่ work - ไม่มี data-category -->
<div id="products">
  <div class="product">iPhone</div>
</div>

<!-- ✅ ต้องมี attribute -->
<div id="products">
  <div class="product" data-category="electronics">iPhone</div>
</div>

⚠️ 3. Wait for Template Render

// ❌ Filter อาจไม่ work ถ้า template ยังไม่ render
TemplateManager.render(data, container);
FilterManager.filter('electronics', '#products', options);

// ✅ รอ template render ก่อน
TemplateManager.render(data, container);
setTimeout(() => {
  FilterManager.filter('electronics', '#products', options);
}, 100);

// ✅ หรือใช้ event listener
EventManager.on('template:render', () => {
  FilterManager.filter('electronics', '#products', options);
});

เอกสารที่เกี่ยวข้อง