Enhances drag and drop functionality
Improves drag and drop event handling, including conversion between all-day and timed events. Introduces HeaderManager to handle header-related event logic and centralizes header event handling for better code organization and separation of concerns. Optimizes event listeners and throttles events for improved performance. Removes redundant code and improves the overall drag and drop experience.
This commit is contained in:
parent
d087e333fe
commit
3bd74d6f4e
6 changed files with 418 additions and 170 deletions
139
src/managers/HeaderManager.ts
Normal file
139
src/managers/HeaderManager.ts
Normal file
|
|
@ -0,0 +1,139 @@
|
|||
import { eventBus } from '../core/EventBus';
|
||||
import { calendarConfig } from '../core/CalendarConfig';
|
||||
import { CalendarTypeFactory } from '../factories/CalendarTypeFactory';
|
||||
|
||||
/**
|
||||
* HeaderManager - Handles all header-related event logic
|
||||
* Separates event handling from rendering concerns
|
||||
*/
|
||||
export class HeaderManager {
|
||||
private headerEventListener: ((event: Event) => void) | null = null;
|
||||
private headerMouseLeaveListener: ((event: Event) => void) | null = null;
|
||||
private cachedCalendarHeader: HTMLElement | null = null;
|
||||
|
||||
constructor() {
|
||||
// Bind methods for event listeners
|
||||
this.setupHeaderDragListeners = this.setupHeaderDragListeners.bind(this);
|
||||
this.destroy = this.destroy.bind(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get cached calendar header element
|
||||
*/
|
||||
private getCalendarHeader(): HTMLElement | null {
|
||||
if (!this.cachedCalendarHeader) {
|
||||
this.cachedCalendarHeader = document.querySelector('swp-calendar-header');
|
||||
}
|
||||
return this.cachedCalendarHeader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup header drag event listeners
|
||||
*/
|
||||
public setupHeaderDragListeners(): void {
|
||||
const calendarHeader = this.getCalendarHeader();
|
||||
if (!calendarHeader) return;
|
||||
|
||||
// Clean up existing listeners first
|
||||
this.removeEventListeners();
|
||||
|
||||
// Throttle for better performance
|
||||
let lastEmitTime = 0;
|
||||
const throttleDelay = 16; // ~60fps
|
||||
|
||||
this.headerEventListener = (event: Event) => {
|
||||
const now = Date.now();
|
||||
if (now - lastEmitTime < throttleDelay) {
|
||||
return; // Throttle events for better performance
|
||||
}
|
||||
lastEmitTime = now;
|
||||
|
||||
const target = event.target as HTMLElement;
|
||||
|
||||
// Optimized element detection
|
||||
const dayHeader = target.closest('swp-day-header');
|
||||
const allDayContainer = target.closest('swp-allday-container');
|
||||
|
||||
if (dayHeader || allDayContainer) {
|
||||
let hoveredElement: HTMLElement;
|
||||
let targetDate: string | undefined;
|
||||
|
||||
if (dayHeader) {
|
||||
hoveredElement = dayHeader as HTMLElement;
|
||||
targetDate = hoveredElement.dataset.date;
|
||||
} else if (allDayContainer) {
|
||||
hoveredElement = allDayContainer as HTMLElement;
|
||||
|
||||
// Optimized day calculation using cached header rect
|
||||
const headerRect = calendarHeader.getBoundingClientRect();
|
||||
const dayHeaders = calendarHeader.querySelectorAll('swp-day-header');
|
||||
const mouseX = (event as MouseEvent).clientX - headerRect.left;
|
||||
const dayWidth = headerRect.width / dayHeaders.length;
|
||||
const dayIndex = Math.max(0, Math.min(dayHeaders.length - 1, Math.floor(mouseX / dayWidth)));
|
||||
|
||||
const targetDayHeader = dayHeaders[dayIndex] as HTMLElement;
|
||||
targetDate = targetDayHeader?.dataset.date;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get header renderer for coordination
|
||||
const calendarType = calendarConfig.getCalendarMode();
|
||||
const headerRenderer = CalendarTypeFactory.getHeaderRenderer(calendarType);
|
||||
|
||||
eventBus.emit('header:mouseover', {
|
||||
element: hoveredElement,
|
||||
targetDate,
|
||||
headerRenderer
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// Header mouseleave listener
|
||||
this.headerMouseLeaveListener = (event: Event) => {
|
||||
eventBus.emit('header:mouseleave', {
|
||||
element: event.target as HTMLElement
|
||||
});
|
||||
};
|
||||
|
||||
// Add event listeners
|
||||
calendarHeader.addEventListener('mouseover', this.headerEventListener);
|
||||
calendarHeader.addEventListener('mouseleave', this.headerMouseLeaveListener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove event listeners from header
|
||||
*/
|
||||
private removeEventListeners(): void {
|
||||
const calendarHeader = this.getCalendarHeader();
|
||||
if (!calendarHeader) return;
|
||||
|
||||
if (this.headerEventListener) {
|
||||
calendarHeader.removeEventListener('mouseover', this.headerEventListener);
|
||||
}
|
||||
|
||||
if (this.headerMouseLeaveListener) {
|
||||
calendarHeader.removeEventListener('mouseleave', this.headerMouseLeaveListener);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear cached header reference
|
||||
*/
|
||||
public clearCache(): void {
|
||||
this.cachedCalendarHeader = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean up resources and event listeners
|
||||
*/
|
||||
public destroy(): void {
|
||||
this.removeEventListeners();
|
||||
|
||||
// Clear references
|
||||
this.headerEventListener = null;
|
||||
this.headerMouseLeaveListener = null;
|
||||
|
||||
this.clearCache();
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue