403Webshell
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 :
current_dir [ Writeable] document_root [ Writeable]

 

Command :


[ Back ]     

Current File : /home/bitrix/ext_www/rospirotorg.ru/bitrix/js/ui/date-picker/src/time-picker-grid.js
import { Dom, Tag, Type, Loc, Runtime, Text } from 'main.core';
import { MemoryCache, type BaseCache } from 'main.core.cache';
import { TimePickerBase, type TimePickerHour, type TimePickerMinute } from './time-picker-base';

import './css/time-picker-grid.css';

export class TimePickerGrid extends TimePickerBase
{
	#refs: BaseCache<HTMLElement> = new MemoryCache();
	#firstRender: boolean = true;

	getContainer(): HTMLElement
	{
		return this.#refs.remember('container', () => {
			return Tag.render`
				<div class="ui-time-picker-grid${this.getDatePicker().isAmPmMode() ? ' --am-pm' : ''}">
					${
						this.getDatePicker().getType() === 'time'
							? null
							: this.getHeaderContainer(this.getPrevBtn(), this.getHeaderTitle())
					}
					<div class="ui-time-picker-grid-content">
						<div class="ui-time-picker-grid-column">
							<div class="ui-time-picker-grid-column-title">${Loc.getMessage('UI_DATE_PICKER_HOURS')}</div>
							<div class="ui-time-picker-grid-column-content">
								${this.getHoursContainer()}
							</div>
						</div>
						<div class="ui-time-picker-grid-column-separator"></div>
						<div class="ui-time-picker-grid-column">
							<div class="ui-time-picker-grid-column-title">${Loc.getMessage('UI_DATE_PICKER_MINUTES')}</div>
							<div class="ui-time-picker-grid-column-content">
								${this.getMinutesContainer()}
							</div>
						</div>
					</div>
				</div>
			`;
		});
	}

	getHeaderTitle(): HTMLElement
	{
		return this.#refs.remember('header-title', () => {
			return Tag.render`
				<div class="ui-time-picker-grid-header-title" onclick="${this.#handleTitleClick.bind(this)}"></div>
			`;
		});
	}

	getHoursContainer(): HTMLElement
	{
		return this.#refs.remember('hours', () => {
			return Tag.render`
				<div 
					class="ui-time-picker-grid-column-items --hours" 
					onclick="${this.#handleItemClick.bind(this)}"
				></div>
			`;
		});
	}

	getMinutesContainer(): HTMLElement
	{
		return this.#refs.remember('minutes', () => {
			return Tag.render`
				<div 
					class="ui-time-picker-grid-column-items --minutes" 
					onclick="${this.#handleItemClick.bind(this)}"
					onscroll="${Runtime.debounce(this.#adjustScrollShadows, 100, this)}"
				></div>
			`;
		});
	}

	onHide()
	{
		super.onHide();
		this.#firstRender = true;
	}

	render()
	{
		super.render();

		let focusedHourBtn: HTMLButtonElement = null;
		this.getHours().forEach((hour: TimePickerHour) => {
			const button: HTMLButtonElement = this.#renderHour(hour, this.getHoursContainer());
			if (hour.focused)
			{
				focusedHourBtn = button;
			}
		});

		let selectedMinute: HTMLElement = null;
		let focusedMinute: HTMLButtonElement = null;
		this.getMinutes().forEach((minute: TimePickerMinute) => {
			const button: HTMLButtonElement = this.#renderMinute(minute, this.getMinutesContainer());
			if (minute.selected)
			{
				selectedMinute = button;
			}

			if (minute.focused)
			{
				focusedMinute = button;
			}
		});

		if (this.#firstRender)
		{
			Dom.style(this.getMinutesContainer(), 'height', `${this.getHoursContainer().offsetHeight}px`);

			if (selectedMinute !== null)
			{
				this.#adjustScrollPosition(selectedMinute, false);
			}

			this.#adjustScrollShadows();

			this.#firstRender = false;
		}

		if (this.getDatePicker().isFocused())
		{
			if (this.getFocusColumn() === 'hours' && focusedHourBtn !== null)
			{
				focusedHourBtn.focus({ preventScroll: true });
			}
			else if (this.getFocusColumn() === 'minutes' && focusedMinute !== null)
			{
				focusedMinute.focus({ preventScroll: true });
			}
		}
	}

	#renderHour(hour: TimePickerHour, container: HTMLElement): HTMLButtonElement
	{
		const button: HTMLButtonElement = this.#refs.remember(`hour-${hour.value}`, () => {
			const hourContainer: HTMLButtonElement = Tag.render`
				<button
					type="button"
					class="ui-time-picker-grid-item" 
					data-index="${hour.index}" 
					data-hour="${hour.value}"
					data-tab-priority="true"
					onmouseenter="${this.#handleMouseEnter.bind(this)}"
					onmouseleave="${this.#handleMouseLeave.bind(this)}"
					onfocus="${this.#handleFocus.bind(this)}"
				><span class="ui-time-picker-grid-item-inner">${hour.name}</span></button>
			`;

			if (this.getDatePicker().isAmPmMode())
			{
				if (hour.value === 0)
				{
					hourContainer.dataset.meridiem = 'AM';
					Dom.addClass(hourContainer, '--has-meridiem');
				}
				else if (hour.value === 12)
				{
					hourContainer.dataset.meridiem = 'PM';
					Dom.addClass(hourContainer, '--has-meridiem');
				}
			}

			Dom.append(hourContainer, container);

			return hourContainer;
		});

		if (hour.selected)
		{
			Dom.addClass(button, '--selected');
		}
		else
		{
			Dom.removeClass(button, '--selected');
		}

		if (hour.focused)
		{
			Dom.addClass(button, '--focused');
		}
		else
		{
			Dom.removeClass(button, '--focused');
		}

		button.tabIndex = hour.tabIndex;

		return button;
	}

	#renderMinute(minute: TimePickerMinute, container: HTMLElement): HTMLButtonElement
	{
		const button: HTMLButtonElement = this.#refs.remember(`minute-${minute.value}`, () => {
			const minuteContainer = Tag.render`
				<button
					type="button"
					class="ui-time-picker-grid-item"
					data-index="${minute.index}" 
					data-minute="${minute.value}"
					onmouseenter="${this.#handleMouseEnter.bind(this)}"
					onmouseleave="${this.#handleMouseLeave.bind(this)}"
					onfocus="${this.#handleFocus.bind(this)}"
				><span class="ui-time-picker-grid-item-inner">${minute.name}</span></button>
			`;

			Dom.append(minuteContainer, container);

			return minuteContainer;
		});

		if (minute.selected)
		{
			Dom.addClass(button, '--selected');
		}
		else
		{
			Dom.removeClass(button, '--selected');
		}

		if (minute.hidden)
		{
			button.dataset.index = '';
			Dom.addClass(button, '--hidden');
		}
		else
		{
			button.dataset.index = minute.index;
			Dom.removeClass(button, '--hidden');
		}

		if (minute.focused)
		{
			Dom.addClass(button, '--focused');
		}
		else
		{
			Dom.removeClass(button, '--focused');
		}

		button.tabIndex = minute.tabIndex;

		return button;
	}

	#adjustScrollPosition(selectedMinute: HTMLElement, smooth: boolean = true): void
	{
		const shadowHeight = 20;
		const scrollTop = this.getMinutesContainer().scrollTop;
		const viewportTop = scrollTop + shadowHeight;

		const offsetTop = selectedMinute.offsetTop;
		const offsetBottom = offsetTop + selectedMinute.offsetHeight;
		const viewportHeight = this.getMinutesContainer().offsetHeight;
		const viewportBottom = scrollTop + viewportHeight - shadowHeight;

		const isVisible = (
			(offsetTop >= viewportTop && offsetTop <= viewportBottom)
			&& (offsetBottom <= viewportBottom && offsetBottom >= viewportTop)
		);

		if (!isVisible)
		{
			this.getMinutesContainer().scrollTo({
				top: selectedMinute.offsetTop - viewportHeight / 2,
				behavior: smooth ? 'smooth' : 'instant',
			});
		}
	}

	adjustMinuteFocusPosition(): void
	{
		const item = this.getContainer().ownerDocument.activeElement;
		if (!item.closest('.ui-time-picker-grid-item'))
		{
			return;
		}

		this.#adjustScrollPosition(item);
	}

	#adjustScrollShadows(): void
	{
		const scrollTop = this.getMinutesContainer().scrollTop;
		const scrollHeight = this.getMinutesContainer().scrollHeight;
		const offsetHeight = this.getMinutesContainer().offsetHeight;
		const columnContainer = this.getMinutesContainer().parentNode.parentNode;
		if (scrollTop > 0)
		{
			Dom.addClass(columnContainer, '--top-shadow');
		}
		else
		{
			Dom.removeClass(columnContainer, '--top-shadow');
		}

		if (scrollTop === scrollHeight - offsetHeight)
		{
			Dom.removeClass(columnContainer, '--bottom-shadow');
		}
		else
		{
			Dom.addClass(columnContainer, '--bottom-shadow');
		}
	}

	#handleItemClick(event: MouseEvent): void
	{
		const item = event.target;
		if (!item.closest('.ui-time-picker-grid-item'))
		{
			return;
		}

		if (Type.isStringFilled(item.dataset.hour))
		{
			this.setFocusColumn('hours');
			const hour = Number(item.dataset.hour);
			this.emit('onSelect', { hour });
		}
		else if (Type.isStringFilled(item.dataset.minute))
		{
			this.setFocusColumn('minutes');
			this.#adjustScrollPosition(item);

			const minute = Number(item.dataset.minute);
			this.emit('onSelect', { minute });
		}
	}

	#handleMouseEnter(event: MouseEvent): void
	{
		const { hour, minute } = event.target.dataset;
		if (Type.isStringFilled(hour))
		{
			this.setFocusColumn('hours');
			this.emit('onFocus', { hour: Text.toInteger(hour) });
		}
		else if (Type.isStringFilled(minute))
		{
			this.setFocusColumn('minutes');
			this.emit('onFocus', { minute: Text.toInteger(minute) });
		}
	}

	#handleMouseLeave(event: MouseEvent): void
	{
		this.emit('onBlur');
	}

	#handleFocus(event: MouseEvent): void
	{
		const { hour, minute } = event.target.dataset;

		const currentColumn = this.getFocusColumn();
		if (Type.isStringFilled(hour))
		{
			this.setFocusColumn('hours');
		}
		else if (Type.isStringFilled(minute))
		{
			this.setFocusColumn('minutes');
		}

		if (currentColumn !== this.getFocusColumn())
		{
			this.render();
		}
	}

	#handleTitleClick(event: MouseEvent): void
	{
		this.emit('onTitleClick');
	}
}

Youez - 2016 - github.com/yon3zu
LinuXploit