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
|
|
@ -11,7 +11,6 @@ import { DateCalculator } from '../utils/DateCalculator';
|
|||
* Optimized to reduce redundant DOM operations and improve performance
|
||||
*/
|
||||
export class GridRenderer {
|
||||
private headerEventListener: ((event: Event) => void) | null = null;
|
||||
private cachedGridContainer: HTMLElement | null = null;
|
||||
private cachedCalendarHeader: HTMLElement | null = null;
|
||||
private cachedTimeAxis: HTMLElement | null = null;
|
||||
|
|
@ -158,8 +157,8 @@ export class GridRenderer {
|
|||
// Always ensure all-day containers exist for all days
|
||||
headerRenderer.ensureAllDayContainers(calendarHeader);
|
||||
|
||||
// Setup optimized event listener
|
||||
this.setupOptimizedHeaderEventListener(calendarHeader);
|
||||
// Setup only grid-related event listeners
|
||||
this.setupGridEventListeners();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -209,83 +208,74 @@ export class GridRenderer {
|
|||
}
|
||||
|
||||
/**
|
||||
* Setup optimized event delegation listener with better performance
|
||||
* Setup grid-only event listeners (column events)
|
||||
*/
|
||||
private setupOptimizedHeaderEventListener(calendarHeader: HTMLElement): void {
|
||||
// Remove existing listener if any
|
||||
if (this.headerEventListener) {
|
||||
calendarHeader.removeEventListener('mouseover', this.headerEventListener);
|
||||
}
|
||||
private setupGridEventListeners(): void {
|
||||
// Setup grid body mouseover listener for all-day to timed conversion
|
||||
this.setupGridBodyMouseOver();
|
||||
}
|
||||
|
||||
// Create optimized listener with throttling
|
||||
/**
|
||||
* Setup grid body mouseover listener for all-day to timed conversion
|
||||
*/
|
||||
private setupGridBodyMouseOver(): void {
|
||||
const grid = this.cachedGridContainer;
|
||||
if (!grid) return;
|
||||
|
||||
const columnContainer = grid.querySelector('swp-day-columns');
|
||||
if (!columnContainer) return;
|
||||
|
||||
// Throttle for better performance
|
||||
let lastEmitTime = 0;
|
||||
const throttleDelay = 16; // ~60fps
|
||||
|
||||
this.headerEventListener = (event) => {
|
||||
|
||||
const gridBodyEventListener = (event: Event) => {
|
||||
const now = Date.now();
|
||||
if (now - lastEmitTime < throttleDelay) {
|
||||
return; // Throttle events for better performance
|
||||
return;
|
||||
}
|
||||
lastEmitTime = now;
|
||||
|
||||
|
||||
const target = event.target as HTMLElement;
|
||||
const dayColumn = target.closest('swp-day-column');
|
||||
|
||||
// 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;
|
||||
if (dayColumn) {
|
||||
const targetColumn = (dayColumn as HTMLElement).dataset.date;
|
||||
if (targetColumn) {
|
||||
// Calculate Y position relative to the column
|
||||
const columnRect = dayColumn.getBoundingClientRect();
|
||||
const mouseY = (event as MouseEvent).clientY;
|
||||
const targetY = mouseY - columnRect.top;
|
||||
|
||||
// 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;
|
||||
eventBus.emit('column:mouseover', {
|
||||
targetColumn,
|
||||
targetY
|
||||
});
|
||||
}
|
||||
|
||||
// Get header renderer once and cache
|
||||
const calendarType = calendarConfig.getCalendarMode();
|
||||
const headerRenderer = CalendarTypeFactory.getHeaderRenderer(calendarType);
|
||||
|
||||
eventBus.emit('header:mouseover', {
|
||||
element: hoveredElement,
|
||||
targetDate,
|
||||
headerRenderer
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// Add the optimized listener
|
||||
calendarHeader.addEventListener('mouseover', this.headerEventListener);
|
||||
|
||||
columnContainer.addEventListener('mouseover', gridBodyEventListener);
|
||||
|
||||
// Store reference for cleanup
|
||||
(this as any).gridBodyEventListener = gridBodyEventListener;
|
||||
(this as any).cachedColumnContainer = columnContainer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean up cached elements and event listeners
|
||||
*/
|
||||
public destroy(): void {
|
||||
// Clean up event listeners
|
||||
if (this.headerEventListener && this.cachedCalendarHeader) {
|
||||
this.cachedCalendarHeader.removeEventListener('mouseover', this.headerEventListener);
|
||||
// Clean up grid-only event listeners
|
||||
if ((this as any).gridBodyEventListener && (this as any).cachedColumnContainer) {
|
||||
(this as any).cachedColumnContainer.removeEventListener('mouseover', (this as any).gridBodyEventListener);
|
||||
}
|
||||
|
||||
// Clear cached references
|
||||
this.cachedGridContainer = null;
|
||||
this.cachedCalendarHeader = null;
|
||||
this.cachedTimeAxis = null;
|
||||
this.headerEventListener = null;
|
||||
(this as any).gridBodyEventListener = null;
|
||||
(this as any).cachedColumnContainer = null;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue