Calendar/wwwroot/js/core/EventBus.js

158 lines
4.7 KiB
JavaScript
Raw Normal View History

2026-02-03 00:02:25 +01:00
/**
* Central event dispatcher for calendar using DOM CustomEvents
* Provides logging and debugging capabilities
*/
export class EventBus {
constructor() {
this.eventLog = [];
this.debug = false;
this.listeners = new Set();
// Log configuration for different categories
this.logConfig = {
calendar: true,
grid: true,
event: true,
scroll: true,
navigation: true,
view: true,
default: true
};
}
/**
* Subscribe to an event via DOM addEventListener
*/
on(eventType, handler, options) {
document.addEventListener(eventType, handler, options);
// Track for cleanup
this.listeners.add({ eventType, handler, options });
// Return unsubscribe function
return () => this.off(eventType, handler);
}
/**
* Subscribe to an event once
*/
once(eventType, handler) {
return this.on(eventType, handler, { once: true });
}
/**
* Unsubscribe from an event
*/
off(eventType, handler) {
document.removeEventListener(eventType, handler);
// Remove from tracking
for (const listener of this.listeners) {
if (listener.eventType === eventType && listener.handler === handler) {
this.listeners.delete(listener);
break;
}
}
}
/**
* Emit an event via DOM CustomEvent
*/
emit(eventType, detail = {}) {
// Validate eventType
if (!eventType) {
return false;
}
const event = new CustomEvent(eventType, {
detail: detail ?? {},
bubbles: true,
cancelable: true
});
// Log event with grouping
if (this.debug) {
this.logEventWithGrouping(eventType, detail);
}
this.eventLog.push({
type: eventType,
detail: detail ?? {},
timestamp: Date.now()
});
// Emit on document (only DOM events now)
return !document.dispatchEvent(event);
}
/**
* Log event with console grouping
*/
logEventWithGrouping(eventType, detail) {
// Extract category from event type (e.g., 'calendar:datechanged' → 'calendar')
const category = this.extractCategory(eventType);
// Only log if category is enabled
if (!this.logConfig[category]) {
return;
}
// Get category emoji and color
const { emoji, color } = this.getCategoryStyle(category);
// Use collapsed group to reduce visual noise
}
/**
* Extract category from event type
*/
extractCategory(eventType) {
if (!eventType) {
return 'unknown';
}
if (eventType.includes(':')) {
return eventType.split(':')[0];
}
// Fallback: try to detect category from event name patterns
const lowerType = eventType.toLowerCase();
if (lowerType.includes('grid') || lowerType.includes('rendered'))
return 'grid';
if (lowerType.includes('event') || lowerType.includes('sync'))
return 'event';
if (lowerType.includes('scroll'))
return 'scroll';
if (lowerType.includes('nav') || lowerType.includes('date'))
return 'navigation';
if (lowerType.includes('view'))
return 'view';
return 'default';
}
/**
* Get styling for different categories
*/
getCategoryStyle(category) {
const styles = {
calendar: { emoji: '🗓️', color: '#2196F3' },
grid: { emoji: '📊', color: '#4CAF50' },
event: { emoji: '📅', color: '#FF9800' },
scroll: { emoji: '📜', color: '#9C27B0' },
navigation: { emoji: '🧭', color: '#F44336' },
view: { emoji: '👁️', color: '#00BCD4' },
default: { emoji: '📢', color: '#607D8B' }
};
return styles[category] || styles.default;
}
/**
* Configure logging for specific categories
*/
setLogConfig(config) {
this.logConfig = { ...this.logConfig, ...config };
}
/**
* Get current log configuration
*/
getLogConfig() {
return { ...this.logConfig };
}
/**
* Get event history
*/
getEventLog(eventType) {
if (eventType) {
return this.eventLog.filter(e => e.type === eventType);
}
return this.eventLog;
}
/**
* Enable/disable debug mode
*/
setDebug(enabled) {
this.debug = enabled;
}
}
// Create singleton instance
export const eventBus = new EventBus();
//# sourceMappingURL=EventBus.js.map