Server IP : 80.87.202.40 / Your IP : 216.73.216.169 Web Server : Apache System : Linux rospirotorg.ru 5.14.0-539.el9.x86_64 #1 SMP PREEMPT_DYNAMIC Thu Dec 5 22:26:13 UTC 2024 x86_64 User : bitrix ( 600) PHP Version : 8.2.27 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : ON | Pkexec : ON Directory : /home/bitrix/ext_www/rospirotorg.ru/bitrix/js/ui/date-picker/src/ |
Upload File : |
import { Type, Event, Dom } from 'main.core'; import { addDate } from './helpers/add-date'; import { cloneDate } from './helpers/clone-date'; import { getDate } from './helpers/get-date'; import { getFocusableBoundaryElements } from './helpers/get-focusable-boundary-elements'; import { setTime } from './helpers/set-time'; import type { DatePicker } from './date-picker'; import type { TimePickerGrid } from './time-picker-grid'; const keyMap = { ArrowRight: { day: 1, month: 1, year: 1, hours: 1, minutes: 1, }, ArrowLeft: { day: -1, month: -1, year: -1, hours: -1, minutes: -1, }, ArrowUp: { day: -7, month: -3, year: -3, hours: -4, minutes: -2, }, ArrowDown: { day: 7, month: 3, year: 3, hours: 4, minutes: 2, }, }; export class KeyboardNavigation { #datePicker: DatePicker = null; #lastFocusElement: HTMLElement = null; constructor(datePicker) { this.#datePicker = datePicker; } init(): void { Event.bind(this.#datePicker.getContainer(), 'keydown', this.#handleKeyDown.bind(this)); Event.bind(this.#datePicker.getContainer(), 'focusin', this.#handleFocusIn.bind(this)); Event.bind(this.#datePicker.getContainer(), 'focusout', this.#handleFocusOut.bind(this)); } #handleKeyDown(event: KeyboardEvent): void { const picker = this.#datePicker; if ( event.key === 'Backspace' && picker.getType() === 'date' && ['year', 'month', 'time'].includes(picker.getCurrentView()) ) { event.preventDefault(); this.resetLastFocusElement(); picker.setCurrentView('day'); return; } if (event.key === 'Tab' && !picker.isInline()) { this.#handleFocusChange(event); return; } const view = picker.getCurrentView(); if (view === 'time' && picker.getTimePickerStyle() === 'wheel') { return; } if (event.key === 'Space' || event.key === 'Enter' || event.key === ' ') { event.preventDefault(); this.resetLastFocusElement(); event.target.click(); } else if (!Type.isUndefined(keyMap[event.key])) { event.preventDefault(); this.resetLastFocusElement(); const initialFocus = picker.getFocusDate() === null && this.#isRootContainerFocused(); if (view === 'time') { const timePicker: TimePickerGrid = this.#datePicker.getPicker('time'); let currentFocusDate = cloneDate(picker.getInitialFocusDate(timePicker.getMode())); let { hours, minutes } = getDate(currentFocusDate); if (initialFocus) { picker.setFocusDate(currentFocusDate); this.#adjustLastFocusElement(); } else if (timePicker.getFocusColumn() === 'hours') { const increment = keyMap[event.key].hours; hours += increment; if (hours < 0) { hours += 24; } else if (hours > 23) { hours -= 24; } currentFocusDate = setTime(currentFocusDate, hours, null, null); picker.setFocusDate(currentFocusDate); this.#adjustLastFocusElement(); } else if (timePicker.getFocusColumn() === 'minutes') { const increment = keyMap[event.key].minutes; minutes += timePicker.getCurrentMinuteStep() * increment; if (minutes < 0) { minutes += 60; } else if (minutes > 59) { minutes -= 60; } currentFocusDate = setTime(currentFocusDate, null, minutes, null); picker.setFocusDate(currentFocusDate); timePicker.adjustMinuteFocusPosition(); this.#adjustLastFocusElement(); } } else { const currentFocusDate = cloneDate(picker.getInitialFocusDate()); if (initialFocus) { picker.setFocusDate(currentFocusDate); } else { const increment = keyMap[event.key][view]; const focusDate = addDate(currentFocusDate, view, increment); picker.setFocusDate(focusDate); } this.#adjustLastFocusElement(); } } } #isRootContainerFocused(): boolean { const rootContainer = this.#datePicker.getContainer(); return rootContainer.ownerDocument.activeElement === rootContainer; } #handleFocusChange(event: KeyboardEvent): void { let prev: HTMLElement = null; let next: HTMLElement = null; const currentPickerContainer = this.#datePicker.getPicker().getContainer(); if (this.#isRootContainerFocused()) { [prev = null, next = null] = getFocusableBoundaryElements( currentPickerContainer, (element: HTMLElement) => element.dataset.tabPriority === 'true', ); } if (prev === null && next === null) { [prev, next] = getFocusableBoundaryElements(currentPickerContainer); } if (event.shiftKey) { prev?.focus({ preventScroll: true, focusVisible: true }); this.setLastFocusElement(prev); } else { next?.focus({ preventScroll: true, focusVisible: true }); this.setLastFocusElement(next); } event.preventDefault(); } setLastFocusElement(element: HTMLElement): void { this.resetLastFocusElement(); this.#lastFocusElement = element; Dom.addClass(this.#lastFocusElement, '--focus-visible'); } resetLastFocusElement(): void { Dom.removeClass(this.#lastFocusElement, '--focus-visible'); this.#lastFocusElement = null; } #adjustLastFocusElement(): void { const rootContainer = this.#datePicker.getContainer(); const activeElement = rootContainer.ownerDocument.activeElement; if (rootContainer.contains(activeElement)) { this.setLastFocusElement(activeElement); } } #handleFocusIn(event: FocusEvent): void { this.resetLastFocusElement(); // this.#lastFocusElement = event.target; } #handleFocusOut(event: FocusEvent): void { this.resetLastFocusElement(); // this.#lastFocusElement = event.target; } }