Your IP : 13.59.69.109


Current Path : /var/www/www-root/data/www/monolith-realty.ru/bitrix/js/location/widget/src/autocomplete/
Upload File :
Current File : /var/www/www-root/data/www/monolith-realty.ru/bitrix/js/location/widget/src/autocomplete/prompt.js

import {EventEmitter} from 'main.core.events';
import {Loc} from 'main.core';
import {Location, Address, AddressType, LocationType} from 'location.core';
import Menu from './menu';

export default class Prompt extends EventEmitter
{
	static onItemSelectedEvent = 'onItemSelected';

	/** Element */
	#inputNode;

	/** Element */
	#menuNode;

	/** {Menu} */
	#menu;

	/** {Array<Location>} */
	#locationList;

	constructor(props)
	{
		super(props);
		this.setEventNamespace('BX.Location.Widget.Prompt');

		this.#inputNode = props.inputNode;

		if (props.menuNode)
		{
			this.#menuNode = props.menuNode;
		}
	}

	#createMenu()
	{
		return new Menu({
			bindElement: this.#menuNode ? this.#menuNode : this.#inputNode,
			autoHide: false,
			closeByEsc: true,
			className: 'location-widget-prompt-menu',
		});
	}

	getMenu(): Menu
	{
		if(!this.#menu || this.#menu.isDestroyed())
		{
			this.#menu = this.#createMenu();
		}

		return this.#menu;
	}

	/**
	 * Show menu with list of locations
	 * @param {array} locationsList
	 * @param {string} searchPhrase
	 * @returns void
	 */
	show(locationsList: Array<Location>, searchPhrase: string): void
	{
		if(locationsList.length > 0)
		{
			this.setMenuItems(locationsList, searchPhrase);
			this.getMenu().show();
		}
	}

	close(): void
	{
		this.getMenu().close();
	}

	/**
	 * @param {array<Location>} locationsList
	 * @param {string} searchPhrase
	 * @param {Address} address
	 * @returns {*}
	 */
	setMenuItems(locationsList: Array<Location>, searchPhrase: string, address: ?Address): Menu
	{
		this.getMenu().clearItems();

		if(Array.isArray(locationsList))
		{
			this.#locationList = locationsList.slice();

			const showFlatList = (
				!address
				|| !address.getFieldValue(AddressType.LOCALITY)
				|| !Prompt.#hasLocationWithLocality(this.#locationList)
			);

			if (showFlatList)
			{
				locationsList.forEach((location, index) => {
					this.getMenu().addMenuItem(
						this.#createMenuItem(index, location, searchPhrase)
					);
				});
			}
			else
			{
				locationsList.forEach((location, index) => {
					if (this.#isAddressOfSameLocation(address, location)) {
						this.getMenu().addMenuItem(
							this.#createMenuItem(index, location, searchPhrase)
						);
					}
				});

				let isSeparatorSet = false;
				locationsList.forEach((location, index) => {
					if (!this.#isAddressOfSameLocation(address, location)) {
						if (!isSeparatorSet)
						{
							this.getMenu().addMenuItem({
								html: Loc.getMessage('LOCATION_WIDGET_PROMPT_IN_OTHER_CITY'),
								delimiter: true
							});
						}

						this.getMenu().addMenuItem(
							this.#createMenuItem(index, location, searchPhrase)
						);
						isSeparatorSet = true;
					}
				});
			}
		}
	}

	#isAddressOfSameLocation(address, location)
	{
		return (
			address
			&& address.getFieldValue(AddressType.LOCALITY)
			&& location
			&& location.address
			&& location.address.getFieldValue(AddressType.LOCALITY)
			&& Prompt.#getAddressPossibleLocalities(location.address).includes(
				address.getFieldValue(AddressType.LOCALITY)
			)
		);
	}

	static #getAddressPossibleLocalities(address: Address)
	{
		const result = [];

		if (address.getFieldValue(AddressType.LOCALITY))
		{
			result.push(address.getFieldValue(AddressType.LOCALITY));
		}

		/**
		 * Address break-down formed on frontend is very inaccurate so we can't rely only on the locality type field
		 * @see #142094
		 */
		if (address.getFieldValue(AddressType.ADM_LEVEL_1))
		{
			result.push(address.getFieldValue(AddressType.ADM_LEVEL_1));
		}

		return result;
	}

	/**
	 * @param {array<Location>} locationsList
	 * @returns boolean
	 */
	static #hasLocationWithLocality(locationsList: Array<Location>): boolean
	{
		for (let location of locationsList)
		{
			if (location.address && location.address.getFieldValue(AddressType.LOCALITY))
			{
				return true;
			}
		}

		return false;
	}

	/**
	 * @param {number} index
	 * @param {Location} location
	 * @param {string} searchPhrase
	 * @returns {{onclick: onclick, text: string}}
	 */
	#createMenuItem(index, location: Location, searchPhrase): Object
	{
		return {
			id: index,
			title: location.name,
			html: Prompt.createMenuItemText(location.name, searchPhrase, location),
			onclick: (event, item) => {
				this.#onItemSelect(index);
				this.close();
			}
		};
	}

	#onItemSelect(index: number): void
	{
		const location = this.#getLocationFromList(index);

		if(location)
		{
			this.emit(Prompt.onItemSelectedEvent, {location: location});
		}
	}

	static createMenuItemText(locationName: string, searchPhrase: string, location: Location): string
	{
		let result = `
		<div>
			<strong>${locationName}</strong>
		</div>`;

		let clarification;

		if(location.getFieldValue(LocationType.TMP_TYPE_CLARIFICATION))
		{
			clarification = location.getFieldValue(LocationType.TMP_TYPE_CLARIFICATION);

			if(clarification)
			{
				if(location.getFieldValue(LocationType.TMP_TYPE_HINT))
				{
					clarification += ` <i>(${location.getFieldValue(LocationType.TMP_TYPE_HINT)})</i>`;
				}

				result += `<div>${clarification}</div>`;
			}
		}

		return '<div data-role="location-widget-menu-item" tabindex="-1">' + result + '</div>';
	}

	static #extractClarification(location: Location): string
	{
		let clarification = '';

		if(location.getFieldValue(LocationType.TMP_TYPE_CLARIFICATION))
		{
			clarification = location.getFieldValue(LocationType.TMP_TYPE_CLARIFICATION);
		}

		return clarification;
	}

	#getLocationFromList(index: number): ?Location
	{
		let result = null;

		if (this.#locationList[index] !== undefined)
		{
			result = this.#locationList[index];
		}

		if(!result)
		{
			BX.debug(`Location with index ${index} was not found`);
		}

		return result;
	}

	choosePrevItem(isRecursive: boolean = false)
	{
		let result = null;
		const item = this.getMenu().choosePrevItem();

		if (item)
		{
			if (item.delimiter && item.delimiter === true)
			{
				result = isRecursive ? this.getMenu().chooseNextItem() : this.choosePrevItem(true);
			}
			else
			{
				result = this.#getLocationFromList(this.getMenu().choseItemIdx);
			}
		}

		return result;
	}

	chooseNextItem()
	{
		let result = null;
		const item = this.getMenu().chooseNextItem();

		if (item)
		{
			if (item.delimiter && item.delimiter === true)
			{
				result = this.chooseNextItem();
			}
			else
			{
				result = this.#getLocationFromList(this.getMenu().choseItemIdx);
			}
		}

		return result;
	}

	isItemChosen()
	{
		return this.getMenu().isItemChosen();
	}

	getChosenItem()
	{
		let result = null;
		const menuItem = this.getMenu().getChosenItem();

		if(menuItem && menuItem.id)
		{
			result = this.#getLocationFromList(this.getMenu().choseItemIdx);
		}

		return result;
	}

	isShown(): boolean
	{
		return this.getMenu().isShown();
	}

	destroy()
	{
		if(this.#menu)
		{
			this.#menu.destroy();
			this.#menu = null;
		}

		this.#locationList = null;
	}
}