UNPKG

devextreme

Version:

JavaScript/TypeScript Component Suite for Responsive Web Development

163 lines (162 loc) 6.25 kB
/** * DevExtreme (esm/__internal/scheduler/appointments_new/appointments.focus_controller.js) * Version: 26.1.3 * Build date: Wed Jun 10 2026 * * Copyright (c) 2012 - 2026 Developer Express Inc. ALL RIGHTS RESERVED * Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/ */ import $ from "../../../core/renderer"; import { focus } from "../../events/m_short"; import { getRawAppointmentGroupValues } from "../utils/resource_manager/appointment_groups_utils"; import { AppointmentCollector } from "./appointment_collector"; export class AppointmentsFocusController { get sortedItems() { return this.appointments.option().getSortedItems() } get isVirtualScrolling() { return this.appointments.option().isVirtualScrolling() } get tabIndex() { return this.appointments.option().tabIndex } constructor(appointments, handlers) { this.appointments = appointments; this.handlers = handlers; this.focusableSortedIndex = 0; this.needRestoreFocusIndex = -1 } onViewItemClick(viewItem) { this.focusViewItem(viewItem) } onViewItemFocusIn() {} onViewItemFocusOut(e) { const focusEvent = e.originalEvent; const $relatedTarget = $(focusEvent.relatedTarget); const { $commonContainer: $commonContainer, $allDayContainer: $allDayContainer } = this.appointments; const isFocusOutside = 0 === $relatedTarget.length || 0 === $relatedTarget.closest($commonContainer).length && 0 === (null === $relatedTarget || void 0 === $relatedTarget ? void 0 : $relatedTarget.closest($allDayContainer ?? $()).length); if (isFocusOutside) { this.resetTabIndex(0) } } onViewItemKeyDown(viewItem, e) { switch (true) { case "Tab" === e.key: this.handleTabKeyDown(e, viewItem.option().sortedIndex); break; case "Delete" === e.key: this.handleDeleteKeyDown(viewItem); break; case "Home" === e.key: this.handleHomeKeyDown(e); break; case "End" === e.key: this.handleEndKeyDown(e); break; case "Enter" === e.key: case " " === e.key: this.handleEnterKeyDown(viewItem, e) } } resetTabIndex(newFocusableIndex) { var _this$appointments$ge2; if (this.needRestoreFocusIndex >= 0) { const viewItem = this.appointments.getViewItemBySortedIndex(this.needRestoreFocusIndex); null === viewItem || void 0 === viewItem || viewItem.setTabIndex(this.tabIndex); focus.trigger(null === viewItem || void 0 === viewItem ? void 0 : viewItem.$element()); this.focusableSortedIndex = this.needRestoreFocusIndex; this.needRestoreFocusIndex = -1; return } if (void 0 !== newFocusableIndex) { var _this$appointments$ge; null === (_this$appointments$ge = this.appointments.getViewItemBySortedIndex(this.focusableSortedIndex)) || void 0 === _this$appointments$ge || _this$appointments$ge.setTabIndex(-1); this.focusableSortedIndex = newFocusableIndex } null === (_this$appointments$ge2 = this.appointments.getViewItemBySortedIndex(this.focusableSortedIndex)) || void 0 === _this$appointments$ge2 || _this$appointments$ge2.setTabIndex(this.tabIndex) } handleTabKeyDown(e, sortedIndex) { const nextIndex = sortedIndex + (e.shift ? -1 : 1); const nextItemData = this.sortedItems[nextIndex]; if (!nextItemData) { return } e.originalEvent.preventDefault(); this.focusBySortedItem(nextItemData) } handleDeleteKeyDown(viewItem) { if (viewItem instanceof AppointmentCollector) { return } const { allowDelete: allowDelete, onDeleteKeyPress: onDeleteKeyPress } = this.appointments.option(); if (!allowDelete) { return } const appointmentViewItem = viewItem; onDeleteKeyPress({ appointmentData: appointmentViewItem.appointmentData, targetedAppointmentData: appointmentViewItem.targetedAppointmentData }) } handleHomeKeyDown(e) { const firstSortedItem = this.sortedItems[0]; if (firstSortedItem) { e.originalEvent.preventDefault(); this.focusBySortedItem(firstSortedItem) } } handleEndKeyDown(e) { const lastSortedItem = this.sortedItems[this.sortedItems.length - 1]; if (lastSortedItem) { e.originalEvent.preventDefault(); this.focusBySortedItem(lastSortedItem) } } handleEnterKeyDown(viewItem, e) { e.originalEvent.preventDefault(); if (viewItem instanceof AppointmentCollector) { return } this.handlers.onAppointmentEnterKeyDown(viewItem, e.originalEvent) } focusBySortedItem(sortedItem) { if (this.isVirtualScrolling) { this.scrollToItem(sortedItem) } const viewItem = this.appointments.getViewItemBySortedIndex(sortedItem.sortedIndex); if (viewItem) { this.focusViewItem(viewItem) } else if (this.isVirtualScrolling) { this.needRestoreFocusIndex = sortedItem.sortedIndex } } focusViewItem(viewItem) { this.resetTabIndex(viewItem.option().sortedIndex); focus.trigger(null === viewItem || void 0 === viewItem ? void 0 : viewItem.$element()) } scrollToItem(sortedItem) { const { getStartViewDate: getStartViewDate, getResourceManager: getResourceManager, scrollTo: scrollTo } = this.appointments.option(); const date = new Date(Math.max(getStartViewDate().getTime(), sortedItem.source.startDate)); const group = getRawAppointmentGroupValues(sortedItem.itemData, getResourceManager().resources); scrollTo(date, { group: group, allDay: sortedItem.allDay }) } }