Current Path : /var/www/www-root/data/www/monolith-realty.ru/bitrix/js/location/widget/src/mappopup/ |
Current File : /var/www/www-root/data/www/monolith-realty.ru/bitrix/js/location/widget/src/mappopup/mappopup.js |
import { Tag, Type, Dom, Event, Loc } from 'main.core'; import { Address, Format, Location, ControlMode, MapBase, GeocodingServiceBase, AddressStringConverter, LocationType } from 'location.core'; import {EventEmitter} from 'main.core.events'; import AddressString from './addressstring'; import AddressApplier from './addressapplier'; import Popup from './popup'; import 'ui.design-tokens'; import './css/mappopup.css'; export default class MapPopup extends EventEmitter { static #onChangedEvent = 'onChanged'; static #onMouseOverEvent = 'onMouseOver'; static #onMouseOutEvent = 'onMouseOut'; static #onShowedEvent = 'onShow'; static #onClosedEvent = 'onClose'; #map; #mode; #address; #popup; #addressString; #addressApplier; #addressFormat; #gallery; #locationRepository; #isMapRendered = false; #mapInnerContainer; #geocodingService; #contentWrapper; #userLocationPoint; constructor(props) { super(props); this.setEventNamespace('BX.Location.Widget.MapPopup'); if (!(props.map instanceof MapBase)) { BX.debug('map must be instance of Map'); } this.#map = props.map; if (props.geocodingService instanceof GeocodingServiceBase) { this.#geocodingService = props.geocodingService; } this.#map.onLocationChangedEventSubscribe(this.#onLocationChanged.bind(this)); if (!(props.popup instanceof Popup)) { BX.debug('popup must be instance of Popup'); } this.#popup = props.popup; if (!(props.addressFormat instanceof Format)) { BX.debug('addressFormat must be instance of Format'); } this.#addressFormat = props.addressFormat; this.#addressString = new AddressString({ addressFormat: this.#addressFormat }); this.#createAddressApplier(); if (props.gallery) { this.#gallery = props.gallery; } this.#locationRepository = props.locationRepository; this.#userLocationPoint = props.userLocationPoint; } #createAddressApplier() { this.#addressApplier = new AddressApplier( { propsData: { address: this.#address, addressFormat: this.#addressFormat, isHidden: true, } } ); this.#addressApplier.$mount(); this.#addressApplier.$on('apply', (event) => { const prevAddress = event.address; this.#address = prevAddress; this.#addressString.address = prevAddress; this.#addressApplier.$props.isHidden = true; this.emit( MapPopup.#onChangedEvent, {address: prevAddress} ); }); } #onLocationChanged(event: Event) { const data = event.getData(); const location = data.location; const address = location.toAddress(); if (!this.#address) { this.#address = address; this.#addressString.address = address; this.emit( MapPopup.#onChangedEvent, {address: address} ); } else if (address.fieldCollection.isEqual(this.#address.fieldCollection, LocationType.ADDRESS_LINE_1)) { this.#address.latitude = address.latitude; this.#address.longitude = address.longitude; if (this.#address.location) { this.#address.location.latitude = address.latitude; this.#address.location.longitude = address.longitude; } this.emit( MapPopup.#onChangedEvent, {address: this.#address} ); this.#addressApplier.$props.isHidden = true; } else { this.#addressString.address = address; this.#addressApplier.$props.address = address; this.#addressApplier.$props.isHidden = false; } if (this.#gallery) { this.#gallery.location = location; } } render(props: object): void { this.#address = props.address; this.#mode = props.mode; this.#isMapRendered = false; this.#mapInnerContainer = Tag.render`<div class="location-map-inner"></div>`; this.#renderPopup(props.bindElement, this.#mapInnerContainer); } #renderPopup(bindElement: Element, mapInnerContainer: Element): Popup { let gallery = ''; if (this.#gallery) { gallery = this.#gallery.render(); } const thirdPartyWarningNode = Tag.render` <div class="location-map-address-third-party-warning"> ${Loc.getMessage('LOCATION_WIDGET_THIRD_PARTY_WARNING')} </div> `; this.#contentWrapper = Tag.render` <div class="location-map-wrapper"> <div class="location-map-container"> ${mapInnerContainer} ${gallery} </div> ${this.#mode === ControlMode.edit ? this.#addressString.render({address: this.#address}) : ''} ${thirdPartyWarningNode} ${this.#mode === ControlMode.edit ? this.#addressApplier.$el : ''} </div>`; Event.bind(this.#contentWrapper, 'click', (e) => e.stopPropagation()); Event.bind(this.#contentWrapper, 'mouseover', (e) => this.emit(MapPopup.#onMouseOverEvent, e)); Event.bind(this.#contentWrapper, 'mouseout', (e) => this.emit(MapPopup.#onMouseOutEvent, e)); this.bindElement = bindElement; this.#popup.setContent(this.#contentWrapper); } get bindElement() { return this.#popup.getBindElement(); } set bindElement(bindElement: Element) { if (Type.isDomNode(bindElement)) { this.#popup.setBindElement(bindElement); } else { BX.debug('bindElement must be type of dom node'); } } set address(address: ?Address): void { this.#address = address; this.#addressString.address = address; this.#convertAddressToLocation(address) .then((location) => { this.#setLocationInternal(location); }); } #extractLatLon(address: Address): ?Array { let result = null; let lat; let lon; if (address.latitude && address.longitude) { lat = address.latitude; lon = address.longitude; } else if (address.location && address.location.latitude && address.location.longitude ) { lat = address.location.latitude; lon = address.location.longitude; } if (lat && lat !== '0' && lon && lon !== '0') { result = [lat, lon]; } return result; } #convertAddressToLocation(address: ?Address, useUserLocation: boolean = false): Promise<?Location> { return new Promise((resolve) => { if (useUserLocation) { resolve( this.#userLocationPoint && this.#mode !== ControlMode.view ? new Location({ latitude: this.#userLocationPoint.latitude, longitude: this.#userLocationPoint.longitude }) : null ); return; } if (address) { const latLon = this.#extractLatLon(address); if (latLon) { resolve(new Location({ latitude: latLon[0], longitude: latLon[1], type: address.getType() })); return; } } resolve(null); }); } #setLocationInternal(location: ?Location): void { if (this.#map) { this.#map.location = location; } if (this.#gallery) { this.#gallery.location = location; } } set mode(mode: string): void { this.#mode = mode; this.#map.mode = mode; } #renderMap({location}) { return this.#map.render({ mapContainer: this.#mapInnerContainer, location: location, mode: this.#mode }); } show(useUserLocation: boolean = false): void { this.#convertAddressToLocation(this.#address, useUserLocation) .then((location) => { if (!location) { return; } this.#popup.show(); if (!this.#isMapRendered) { this.#renderMap({location}) .then(() => { if (this.#gallery) { this.#gallery.location = location; } this.emit(MapPopup.#onShowedEvent); this.#map.onMapShow(); }); this.#isMapRendered = true; } else { this.#map.location = location; if (this.#gallery) { this.#gallery.location = location; } this.emit(MapPopup.#onShowedEvent); this.#map.onMapShow(); } }); } isShown(): boolean { return this.#popup.isShown(); } close(): void { this.#popup.close(); this.#addressApplier.$props.isHidden = true; this.emit(MapPopup.#onClosedEvent); } onChangedEventSubscribe(listener: Function): void { this.subscribe(MapPopup.#onChangedEvent, listener); } onMouseOverSubscribe(listener: Function): void { this.subscribe(MapPopup.#onMouseOverEvent, listener); } onMouseOutSubscribe(listener: Function): void { this.subscribe(MapPopup.#onMouseOutEvent, listener); } subscribeOnShowedEvent(listener: Function): void { this.subscribe(MapPopup.#onShowedEvent, listener); } subscribeOnClosedEvent(listener: Function): void { this.subscribe(MapPopup.#onClosedEvent, listener); } destroy() { this.#map = null; this.#gallery = null; this.#addressString = null; this.#addressApplier = null; this.#popup.destroy(); this.#popup = null; Dom.remove(this.#contentWrapper); this.#contentWrapper = null; Event.unbindAll(this); } }