Now.js Framework Documentation
DropdownPanel
DropdownPanel
ภาพรวม
DropdownPanel คือ singleton panel สำหรับแสดง dropdown content ใน Now.js Framework ใช้แชร์ระหว่าง components เช่น Calendar และ ColorPicker
ใช้เมื่อ:
- ต้องการ dropdown floating panel
- ต้องการ share panel ระหว่าง components
- ต้องการ avoid z-index issues ใน modals
- ต้องการ popup positioning
ทำไมต้องใช้:
- ✅ Singleton pattern (one panel for all)
- ✅ Attached to document.body (no overflow issues)
- ✅ Smart positioning (auto-adjust to viewport)
- ✅ Keyboard support (Escape to close)
- ✅ Click outside to close
- ✅ Scroll/resize repositioning
การใช้งานพื้นฐาน
Show Panel
const panel = DropdownPanel.getInstance();
// Show with HTML content
panel.show(targetElement, '<div class="picker">Content here</div>');
// Show with DOM element
const content = document.createElement('div');
content.innerHTML = '<p>My content</p>';
panel.show(targetElement, content);
// With options
panel.show(targetElement, content, {
align: 'right',
offsetY: 10,
onClose: () => console.log('Panel closed')
});Hide Panel
const panel = DropdownPanel.getInstance();
panel.hide();Options
panel.show(targetElement, content, {
// Alignment relative to target
align: 'left', // 'left', 'right', 'center'
// Offset from target
offsetY: 5, // Vertical offset (px)
offsetX: 0, // Horizontal offset (px)
// Callback when closed
onClose: () => {}
});API อ้างอิง
DropdownPanel.getInstance()
รับ singleton instance
Returns: DropdownPanel
const panel = DropdownPanel.getInstance();panel.show(targetElement, content, options?)
แสดง panel
| Parameter | Type | Description |
|---|---|---|
targetElement |
HTMLElement | Element ที่จะ position ถัดจาก |
content |
HTMLElement/string | Content (element หรือ HTML string) |
options.align |
string | 'left', 'right', 'center' |
options.offsetY |
number | Vertical offset (default: 5) |
options.offsetX |
number | Horizontal offset (default: 0) |
options.onClose |
function | Callback เมื่อปิด |
panel.hide()
ซ่อน panel
panel.isOpen()
ตรวจสอบว่า panel เปิดอยู่หรือไม่
Returns: boolean
panel.setContent(content)
เปลี่ยน content ขณะที่แสดงอยู่
| Parameter | Type | Description |
|---|---|---|
content |
HTMLElement/string | New content |
panel.getContentContainer()
รับ content container element
Returns: HTMLElement
DropdownPanel.destroy()
ทำลาย singleton instance
เหตุการณ์
| Event | เมื่อเกิด | Detail |
|---|---|---|
dropdown:show |
Panel แสดง | {target} |
dropdown:hide |
Panel ซ่อน | {target} |
const panel = DropdownPanel.getInstance();
panel.panel.addEventListener('dropdown:show', (e) => {
console.log('Opened for:', e.detail.target);
});การจัดรูปแบบ CSS
/* Dropdown panel */
.dropdown-panel {
position: fixed;
display: none;
background: white;
border: 1px solid #e5e7eb;
border-radius: 8px;
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
z-index: 1000;
overflow: auto;
}
.dropdown-panel-content {
padding: 8px;
}
/* Animation */
.dropdown-panel {
animation: dropdown-fade-in 0.15s ease-out;
}
@keyframes dropdown-fade-in {
from {
opacity: 0;
transform: translateY(-8px);
}
to {
opacity: 1;
transform: translateY(0);
}
}ตัวอย่างการใช้งานจริง
Color Picker
function showColorPicker(inputElement) {
const panel = DropdownPanel.getInstance();
const picker = document.createElement('div');
picker.className = 'color-picker-grid';
picker.innerHTML = `
<div class="color" style="background: #ff0000" data-color="#ff0000"></div>
<div class="color" style="background: #00ff00" data-color="#00ff00"></div>
<div class="color" style="background: #0000ff" data-color="#0000ff"></div>
`;
picker.addEventListener('click', (e) => {
const color = e.target.dataset.color;
if (color) {
inputElement.value = color;
inputElement.style.backgroundColor = color;
panel.hide();
}
});
panel.show(inputElement, picker, {
onClose: () => {
// Cleanup if needed
}
});
}Date Picker
function showDatePicker(inputElement, currentDate) {
const panel = DropdownPanel.getInstance();
const calendar = CalendarManager.createCalendarElement({
date: currentDate,
onSelect: (date) => {
inputElement.value = Utils.date.format(date, 'YYYY-MM-DD');
panel.hide();
}
});
panel.show(inputElement, calendar, {
align: 'left',
offsetY: 4
});
}Context Menu
function showContextMenu(event, items) {
event.preventDefault();
const panel = DropdownPanel.getInstance();
const menu = document.createElement('ul');
menu.className = 'context-menu';
items.forEach(item => {
const li = document.createElement('li');
li.textContent = item.label;
li.addEventListener('click', () => {
item.action();
panel.hide();
});
menu.appendChild(li);
});
// Create virtual target at click position
const virtualTarget = document.createElement('span');
virtualTarget.style.cssText = `
position: fixed;
left: ${event.clientX}px;
top: ${event.clientY}px;
`;
document.body.appendChild(virtualTarget);
panel.show(virtualTarget, menu, {
onClose: () => virtualTarget.remove()
});
}ข้อควรระวัง
⚠️ 1. Singleton - มีได้แค่ panel เดียว
// ❌ เปิด 2 panels พร้อมกัน
panel.show(element1, content1);
panel.show(element2, content2); // อันแรกถูกปิด
// ✅ เข้าใจว่ามีได้แค่ 1 panel
// ถ้าต้องการหลาย popup ให้ใช้ DialogManager⚠️ 2. Target Element ต้องมีอยู่
// ❌ Target ไม่มีอยู่จริง
panel.show(null, content);
// ✅ ตรวจสอบก่อน
if (targetElement) {
panel.show(targetElement, content);
}⚠️ 3. Clean up เมื่อไม่ใช้
// onClose callback สำหรับ cleanup
panel.show(target, content, {
onClose: () => {
// Cleanup resources
disposeResources();
}
});เอกสารที่เกี่ยวข้อง
- CalendarManager - Calendar component
- DialogManager - Dialog boxes
- BackdropManager - Backdrops