@syncfusion/ej2-maps
Version:
The Maps component is used to visualize the geographical data and represent the statistical data of a particular geographical area on earth with user interactivity, and provides various customizing options
1,348 lines (1,296 loc) • 154 kB
text/typescript
/**
* Maps Component file
*/
import { Component, NotifyPropertyChanges, INotifyPropertyChanged, Property, Fetch } from '@syncfusion/ej2-base';
import { EventHandler, Browser, EmitType, isNullOrUndefined, createElement, setValue, extend } from '@syncfusion/ej2-base';
import { Event, remove, L10n, Collection, Internationalization, Complex } from '@syncfusion/ej2-base';
import { ModuleDeclaration } from '@syncfusion/ej2-base';
import { SvgRenderer } from '@syncfusion/ej2-svg-base';
import { Size, createSvg, Point, removeElement, triggerShapeEvent, showTooltip, checkShapeDataFields, MapLocation, getMousePosition, calculateSize } from './utils/helper';
import { getElement, removeClass, getTranslate, triggerItemSelectionEvent, mergeSeparateCluster, customizeStyle, querySelector } from './utils/helper';
import { createStyle, getProcessedMarginValue } from './utils/helper';
import { ZoomSettings, LegendSettings } from './model/base';
import { LayerSettings, TitleSettings, Border, Margin, MapsAreaSettings, Annotation, CenterPosition } from './model/base';
import { ZoomSettingsModel, LegendSettingsModel, LayerSettingsModel, BubbleSettingsModel, PolygonSettingsModel } from './model/base-model';
import { MarkerSettingsModel, SelectionSettingsModel, InitialMarkerSelectionSettingsModel } from './model/base-model';
import { TitleSettingsModel, BorderModel, MarginModel, CenterPositionModel, InitialShapeSelectionSettingsModel } from './model/base-model';
import { MapsAreaSettingsModel, AnnotationModel } from './model/base-model';
import { Bubble } from './layers/bubble';
import { Legend } from './layers/legend';
import { Marker } from './layers/marker';
import { Highlight } from './user-interaction/highlight';
import { Selection } from './user-interaction/selection';
import { MapsTooltip } from './user-interaction/tooltip';
import { Zoom } from './user-interaction/zoom';
import { load, click, onclick, rightClick, doubleClick, resize, shapeSelected, zoomIn, mouseMove } from './model/constants';
import { ProjectionType, MapsTheme, PanDirection, TooltipGesture } from './utils/enum';
import { MapsModel } from './maps-model';
import { getThemeStyle, Theme } from './model/theme';
import { ILoadEventArgs, ILoadedEventArgs, IMinMaxLatitudeLongitude, IMouseEventArgs, IMouseMoveEventArgs, IResizeEventArgs, ITooltipRenderEventArgs } from './model/interface';
import { GeoPosition, ITooltipRenderCompleteEventArgs, ILegendRenderingEventArgs } from './model/interface';
import { ILayerRenderingEventArgs, IShapeRenderingEventArgs, IMarkerRenderingEventArgs, IMarkerClickEventArgs } from './model/interface';
import { IMarkerMoveEventArgs, ILabelRenderingEventArgs, IBubbleMoveEventArgs, IBubbleClickEventArgs } from './model/interface';
import { IMarkerClusterClickEventArgs, IMarkerClusterMoveEventArgs, IMarkerClusterRenderingEventArgs } from './model/interface';
import { ISelectionEventArgs, IShapeSelectedEventArgs, IMapPanEventArgs, IMapZoomEventArgs } from './model/interface';
import { IBubbleRenderingEventArgs, IAnimationCompleteEventArgs, IPrintEventArgs, IThemeStyle } from './model/interface';
import { LayerPanel } from './layers/layer-panel';
import { GeoLocation, Rect, RectOption, measureText, getElementByID, MapAjax, processResult, getElementsByClassName } from '../maps/utils/helper';
import { findPosition, textTrim, TextOption, renderTextElement, calculateZoomLevel, convertTileLatLongToPoint, convertGeoToPoint} from '../maps/utils/helper';
import { Annotations } from '../maps/user-interaction/annotation';
import { FontModel, DataLabel, MarkerSettings, IAnnotationRenderingEventArgs, IMarkerDragEventArgs, BingMap } from './index';
import { NavigationLineSettingsModel, changeBorderWidth } from './index';
import { NavigationLine } from './layers/navigation-selected-line';
import { Polygon } from './layers/polygon';
import { DataManager, Query } from '@syncfusion/ej2-data';
import { ExportType } from '../maps/utils/enum';
import { PdfPageOrientation } from '@syncfusion/ej2-pdf-export';
import { Print } from './model/print';
import { PdfExport } from './model/export-pdf';
import { ImageExport } from './model/export-image';
/**
* Represents the maps control. It is ideal for rendering maps from GeoJSON data or other map providers like OpenStreetMap, Google Maps, Bing Maps, etc that
* has rich feature set that includes markers, labels, bubbles and much more.
* ```html
* <div id="maps"/>
* <script>
* var maps = new Maps();
* maps.appendTo("#maps");
* </script>
* ```
*/
@NotifyPropertyChanges
export class Maps extends Component<HTMLElement> implements INotifyPropertyChanged {
//Module Declaration of Maps.
/**
* Gets or sets the module to add bubbles in the maps.
*
* @private
*/
public bubbleModule: Bubble;
/**
* Sets and get the module to add the marker in the maps.
*
* @private
*/
public markerModule: Marker;
/**
* Gets or sets the module to add the data-label in the maps.
*
* @private
*/
public dataLabelModule: DataLabel;
/**
* Gets or sets the module to highlight the element when mouse has hovered on it in maps.
*
* @private
*/
public highlightModule: Highlight;
/**
* Gets or sets the module to add the navigation lines in the maps.
*
* @private
*/
public navigationLineModule: NavigationLine;
/**
* Gets or sets the module to add the polygon shapes over the maps.
*
* @private
*/
public polygonModule: Polygon;
/**
* Gets or sets the module to add the legend in maps.
*
* @private
*/
public legendModule: Legend;
/**
* Gets or sets the module to select the geometric shapes when clicking in maps.
*
* @private
*/
public selectionModule: Selection;
/**
* Gets or sets the module to add the tooltip when mouse has hovered on an element in maps.
*
* @private
*/
public mapsTooltipModule: MapsTooltip;
/**
* Gets or sets the module to add the zooming operations in maps.
*
* @private
*/
public zoomModule: Zoom;
/**
* Gets or sets the module to add annotation elements in maps.
*
* @private
*/
public annotationsModule: Annotations;
/**
* This module enables the print functionality in maps.
*
* @private
*/
public printModule: Print;
/**
* This module enables the export to PDF functionality in maps.
*
* @private
*/
public pdfExportModule: PdfExport;
/**
* This module enables the export to image functionality in maps.
*
* @private
*/
public imageExportModule: ImageExport;
/**
* This module enables the bing map functionality in maps.
*
* @private
*/
public bingMap: BingMap;
// Maps pblic API Declaration
/**
* Gets or sets the background color of the maps container.
*
* @default null
*/
@Property(null)
public background: string;
/**
* Enables or disables the visibility state of the separator for grouping.
*
* @default false
*/
@Property(false)
public useGroupingSeparator: boolean;
/**
* Gets or sets the format to apply internationalization for the text in the maps.
*
* @default null
*/
@Property(null)
public format: string;
/**
* Gets or sets the width in which the maps is to be rendered.
*
* @default null
*/
@Property(null)
public width: string;
/**
* Gets or sets the height in which the maps is to be rendered.
*
* @default null
*/
@Property(null)
public height: string;
/**
* Gets or sets the mode in which the tooltip is to be displayed.
* The tooltip can be rendered on mouse move, click or double clicking on the
* element on the map.
*
* @default 'MouseMove'
*/
@Property('MouseMove')
public tooltipDisplayMode: TooltipGesture;
/**
* Enables or disables the print functionality in maps.
*
* @default false
*/
@Property(false)
public allowPrint: boolean;
/**
* Enables or disables the export to image functionality in maps.
*
* @default false
*/
@Property(false)
public allowImageExport: boolean;
/**
* Enables or disables the export to PDF functionality in maps.
*
* @default false
*/
@Property(false)
public allowPdfExport: boolean;
/**
* Gets or sets the options to customize the title of the maps.
*/
@Complex<TitleSettingsModel>({}, TitleSettings)
public titleSettings: TitleSettingsModel;
/**
* Gets or sets the options to customize the zooming operations in maps.
*/
@Complex<ZoomSettingsModel>({}, ZoomSettings)
public zoomSettings: ZoomSettingsModel;
/**
* Gets or sets the options to customize the legend of the maps.
*/
@Complex<LegendSettingsModel>({}, LegendSettings)
public legendSettings: LegendSettingsModel;
/**
* Gets or sets the options to customize the layers of the maps.
*/
@Collection<LayerSettingsModel>([], LayerSettings)
public layers: LayerSettingsModel[];
/**
* Gets or sets the options for customizing the annotations in the maps.
*/
@Collection<AnnotationModel>([], Annotation)
public annotations: AnnotationModel[];
/**
* Gets or sets the options to customize the margin of the maps.
*/
@Complex<MarginModel>({}, Margin)
public margin: MarginModel;
/**
* Gets or sets the options for customizing the style properties of the maps border.
*/
@Complex<BorderModel>({ color: '#DDDDDD', width: 0 }, Border)
public border: BorderModel;
/**
* Gets or sets the theme styles supported for maps. When the theme is set, the styles associated with the theme will be set in the maps.
*
* @default Material
*/
@Property('Material')
public theme: MapsTheme;
/**
* Gets or sets the projection with which the maps will be rendered to show the two-dimensional curved surface of a globe on a plane.
*
* @default Mercator
*/
@Property('Mercator')
public projectionType: ProjectionType;
/**
* Gets or sets the index of the layer of maps which will be the base layer. It provides the option to select which layer to be visible in the maps.
*
* @default 0
*/
@Property(0)
public baseLayerIndex: number;
/**
* Gets or sets the description of the maps for assistive technology.
*
* @default null
*/
@Property(null)
public description: string;
/**
* Gets or sets the tab index value for the maps.
*
* @default 0
*/
@Property(0)
public tabIndex: number;
/**
* Gets or sets the center position of the maps.
*/
@Complex<CenterPositionModel>({ latitude: null, longitude: null }, CenterPosition)
public centerPosition: CenterPositionModel;
/**
* Gets or sets the options to customize the area around the map.
*/
@Complex<MapsAreaSettingsModel>({}, MapsAreaSettings)
public mapsArea: MapsAreaSettingsModel;
/**
* Triggers before the maps gets rendered.
*
* @event load
*/
@Event()
public load: EmitType<ILoadEventArgs>;
/**
* Triggers before the print gets started.
*
* @event beforePrint
*/
@Event()
public beforePrint: EmitType<IPrintEventArgs>;
/**
* Triggers after the maps gets rendered.
*
* @event loaded
*/
@Event()
public loaded: EmitType<ILoadedEventArgs>;
/**
* Triggers when a user clicks on an element in Maps.
*
* @event click
* @deprecated
*/
@Event()
public click: EmitType<IMouseEventArgs>;
/**
* Triggers when a user clicks on an element in Maps.
*
* @event onclick
*/
@Event()
public onclick: EmitType<IMouseEventArgs>;
/**
* Triggers when performing the double click operation on an element in maps.
*
* @event doubleClick
*/
@Event()
public doubleClick: EmitType<IMouseEventArgs>;
/**
* Triggers when performing the right click operation on an element in maps.
*
* @event rightClick
*/
@Event()
public rightClick: EmitType<IMouseEventArgs>;
/**
* Triggers to notify the resize of the maps when the window is resized.
*
* @event resize
*/
@Event()
public resize: EmitType<IResizeEventArgs>;
/**
* Triggers before the maps tooltip gets rendered.
*
* @event tooltipRender
*/
@Event()
public tooltipRender: EmitType<ITooltipRenderEventArgs>;
/**
* Triggers before the legend gets rendered.
*
* @event legendRendering
* @deprecated
*/
@Event()
public legendRendering: EmitType<ILegendRenderingEventArgs>;
/**
* Triggers after the maps tooltip gets rendered.
*
* @deprecated
* @event tooltipRenderComplete
*/
@Event()
public tooltipRenderComplete: EmitType<ITooltipRenderCompleteEventArgs>;
/**
* Triggers when a shape is selected in the maps.
*
* @event shapeSelected
*/
@Event()
public shapeSelected: EmitType<IShapeSelectedEventArgs>;
/**
* Triggers before the shape, bubble or marker gets selected.
*
* @event itemSelection
*/
@Event()
public itemSelection: EmitType<ISelectionEventArgs>;
/**
* Trigger before the shape, bubble or marker gets highlighted.
*
* @event itemHighlight
*/
@Event()
public itemHighlight: EmitType<ISelectionEventArgs>;
/**
* Triggers before the shape gets highlighted.
*
* @event shapeHighlight
*/
@Event()
public shapeHighlight: EmitType<IShapeSelectedEventArgs>;
/**
* Triggers before the maps layer gets rendered.
*
* @event layerRendering
*/
@Event()
public layerRendering: EmitType<ILayerRenderingEventArgs>;
/**
* Triggers before the maps shape gets rendered.
*
* @event shapeRendering
*/
@Event()
public shapeRendering: EmitType<IShapeRenderingEventArgs>;
/**
* Triggers before the maps marker gets rendered.
*
* @event markerRendering
*/
@Event()
public markerRendering: EmitType<IMarkerRenderingEventArgs>;
/**
* Triggers before the maps marker cluster gets rendered.
*
* @event markerClusterRendering
*/
@Event()
public markerClusterRendering: EmitType<IMarkerClusterRenderingEventArgs>;
/**
* Triggers when clicking on a marker element.
*
* @event markerClick
*/
@Event()
public markerClick: EmitType<IMarkerClickEventArgs>;
/**
* When the marker begins to drag on the map, this event is triggered.
*
* @event markerDragStart
*/
@Event()
public markerDragStart: EmitType<IMarkerDragEventArgs>;
/**
* When the marker has stopped dragging on the map, this event is triggered.
*
* @event markerDragEnd
*/
@Event()
public markerDragEnd: EmitType<IMarkerDragEventArgs>;
/**
* Triggers when clicking the marker cluster in maps.
*
* @event markerClusterClick
*/
@Event()
public markerClusterClick: EmitType<IMarkerClusterClickEventArgs>;
/**
* Triggers when moving the mouse over the marker cluster element in maps.
*
* @event markerClusterMouseMove
*/
@Event()
public markerClusterMouseMove: EmitType<IMarkerClusterMoveEventArgs>;
/**
* Triggers when moving the mouse over the marker element in maps.
*
* @event markerMouseMove
*/
@Event()
public markerMouseMove: EmitType<IMarkerMoveEventArgs>;
/**
* This event is triggered when the mouse pointer moves over the map.
*
* @event mouseMove
*/
@Event()
public mouseMove: EmitType<IMouseMoveEventArgs>;
/**
* Triggers before the data-label gets rendered.
*
* @event dataLabelRendering
*/
@Event()
public dataLabelRendering: EmitType<ILabelRenderingEventArgs>;
/**
* Triggers before the bubble element gets rendered on the map.
*
* @event bubbleRendering
*/
@Event()
public bubbleRendering: EmitType<IBubbleRenderingEventArgs>;
/**
* Triggers when performing the click operation on the bubble element in maps.
*
* @event bubbleClick
*/
@Event()
public bubbleClick: EmitType<IBubbleClickEventArgs>;
/**
* Triggers when hovering the mouse on the bubble element in maps.
*
* @event bubbleMouseMove
*/
@Event()
public bubbleMouseMove: EmitType<IBubbleMoveEventArgs>;
/**
* Triggers after the animation is completed in the maps.
*
* @event animationComplete
*/
@Event()
public animationComplete: EmitType<IAnimationCompleteEventArgs>;
/**
* Triggers before rendering an annotation in the maps.
*
* @event annotationRendering
*/
@Event()
public annotationRendering: EmitType<IAnnotationRenderingEventArgs>;
/**
* Triggers before the zoom operations such as zoom in and zoom out in the maps.
*
* @event zoom
*/
@Event()
public zoom: EmitType<IMapZoomEventArgs>;
/**
* Triggers before performing the panning operation.
*
* @event pan
*/
@Event()
public pan: EmitType<IMapPanEventArgs>;
/**
* This event is triggered after performing the panning action.
*
* @event panComplete
*/
@Event()
public panComplete: EmitType<IMapPanEventArgs>;
/**
* This event is triggered after the zooming operation is completed.
*
* @event zoomComplete
*/
@Event()
public zoomComplete: EmitType<IMapPanEventArgs>;
// Internal properties declaration area.
/**
* Specifies the function to format the text contents in the maps.
*
* @private
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
public formatFunction: any;
/**
* Specifies the svg renderer object.
*
* @private
*/
public renderer: SvgRenderer;
/**
* Specifies the svg element's object of maps.
*
* @private
*/
public svgObject: Element;
/** @public */
public mapScaleValue: number;
/**
* Specifies the available height and width of maps.
*
* @private
*/
public availableSize: Size;
/**
* whether it is layer add or not.
*
* @private
*/
public isAddLayer: boolean;
/**
* Specifies the localization object.
*
* @private
*/
public localeObject: L10n;
/**
* Specifies the default values of localization values.
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
private defaultLocalConstants: any;
/**
* Internal use of internationalization instance.
*
* @private
*/
public intl: Internationalization;
/**
* Check layer whether is geometry or tile.
*
* @private
*/
public isTileMap: boolean = false;
/**
* Resize the map
*/
private resizeTo: number;
/**
* Resize the map
*
* @private
*/
public isResize: boolean = false;
/**
* @private
*/
public mapAreaRect: Rect;
/**
* @private
*/
public layersCollection: LayerSettings[];
/**
* @private
*/
public isExportInitialTileMap: boolean;
/**
* @private
* @hidden
*/
public mapLayerPanel: LayerPanel;
/**
* @private
* @hidden
*/
/**
* @private
*/
public themeStyle: IThemeStyle;
/**
* @private
*/
public isReset: boolean = false;
/**
* @private
*/
public totalRect: Rect;
/**
*
* Specifies whether the shape is selected in the maps or not.
*
* @returns {boolean} - Returns a boolean value to specify whether the shape is selected in the maps or not.
*/
public get isShapeSelected(): boolean {
return this.mapSelect;
}
public dataLabel: DataLabel;
/** @private */
public isTouch: boolean;
/** @private */
public baseSize: Size = new Size(0, 0);
/** @private */
public scale: number;
/** @private */
public baseScale: number;
/** @private */
public mapSelect: boolean;
/** @private */
public baseMapBounds: GeoLocation;
/** @private */
// eslint-disable-next-line @typescript-eslint/no-explicit-any
public baseMapRectBounds: any;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
private resizeEvent: any;
/** @public */
public translatePoint: Point = new Point(0, 0);
/** @private */
public baseTranslatePoint: Point = new Point(0, 0);
/** @public */
public zoomTranslatePoint: Point = new Point(0, 0);
/** @private */
public markerZoomFactor: number;
/** @private */
public markerZoomCenterPoint: CenterPositionModel;
/** @private */
public markerZoomedState: boolean = true;
/** @private */
public zoomPersistence: boolean = false;
/** @private */
public defaultState: boolean = true;
/** @private */
public currentTiles: HTMLElement;
/** @private */
public markerCenterLatitude: number;
/** @private */
public markerCenterLongitude: number;
/** @private */
public previousCenterLatitude: number;
/** @private */
public previousCenterLongitude: number;
/** @private */
public centerPositionChanged: boolean = false;
/** @private */
public previousZoomFactor: number;
/** @private */
public shouldZoomCurrentFactor: number;
/** @private */
public shouldZoomPreviousFactor: number;
/** @private */
public markerNullCount: number = 0;
/** @private */
public translateType: string;
/** @public */
// eslint-disable-next-line @typescript-eslint/ban-types
public previousProjection: String;
/** @private */
public currentShapeDataLength: number;
/** @private */
public tileTranslatePoint: Point = new Point(0, 0);
/** @private */
public baseTileTranslatePoint: Point = new Point(0, 0);
/** @private */
// eslint-disable-next-line @typescript-eslint/ban-types
public isDevice: Boolean = false;
/** @private */
public tileZoomLevel: number;
/** @private */
public isZoomByPosition: boolean;
/** @private */
public tileZoomScale: number;
/** @private */
public staticMapZoom: number = this.zoomSettings.enable ? this.zoomSettings.zoomFactor : 0;
/** @private */
// eslint-disable-next-line @typescript-eslint/no-explicit-any
public serverProcess: any;
/** @private */
// eslint-disable-next-line @typescript-eslint/no-explicit-any
public toolbarProperties: any;
/** @private */
public previousScale: number;
/** @private */
public previousPoint: Point;
/** @private */
public centerLatOfGivenLocation: number;
/** @private */
public centerLongOfGivenLocation: number;
/** @private */
public minLatOfGivenLocation: number;
/** @private */
public minLongOfGivenLocation: number;
/** @private */
public maxLatOfGivenLocation: number;
/** @private */
public maxLongOfGivenLocation: number;
/** @private */
public scaleOfGivenLocation: number;
/** @private */
public zoomNotApplied: boolean = false;
/** @public */
public dataLabelShape: number[] = [];
public zoomShapeCollection: string[] = [];
public zoomLabelPositions: object[] = [];
public mouseDownEvent: Object = { x: null, y: null };
public mouseClickEvent: Object = { x: null, y: null };
/** @private */
public shapeSelectionClass: Element;
/** @private */
public selectedElementId: string[] = [];
/** @private */
public markerSelectionClass: Element;
/** @private */
public selectedMarkerElementId: string[] = [];
/** @private */
public bubbleSelectionClass: Element;
/** @private */
public selectedBubbleElementId: string[] = [];
/** @private */
public navigationSelectionClass: Element;
/** @private */
public selectedNavigationElementId: string[] = [];
/** @private */
public polygonSelectionClass: Element;
/** @private */
public selectedPolygonElementId: string[] = [];
/** @private */
public legendSelectionClass: SelectionSettingsModel;
/** @private */
public selectedLegendElementId: number[] = [];
/** @private */
// eslint-disable-next-line @typescript-eslint/no-explicit-any
public legendSelectionCollection: any[] = [];
/** @private */
public shapeSelections: boolean = true;
/** @private */
public legendSelection: boolean = true;
/** @private */
public toggledLegendId: number[] = [];
/** @private */
public toggledElementId: string[] = [];
/** @private */
public checkInitialRender: boolean = true;
/** @private */
public widthBeforeRefresh: number;
/** @private */
public heightBeforeRefresh: number;
/** @private */
public previousTranslate: Point;
/** @private */
public initialTileTranslate: Point = new Point(0, 0);
/** @private */
public previousTileWidth: number;
/** @private */
public isMarkerZoomCompleted: boolean = false;
/** @private */
public markerDragId: string = '';
/** @private */
public previousTileHeight: number;
/** @private */
public initialZoomLevel: number;
/** @private */
public initialCheck: boolean = true;
/** @private */
public applyZoomReset: boolean = false;
/** @private */
public markerClusterExpandCheck: boolean = false;
/** @private */
public markerClusterExpand: boolean = false;
/** @private */
public mouseMoveId: string = '';
/** @private */
// eslint-disable-next-line @typescript-eslint/no-explicit-any
public shapeSelectionItem: any[] = [];
/** @private */
// eslint-disable-next-line @typescript-eslint/no-explicit-any
public markerDragArgument: any = null;
/**
* Constructor for creating the widget.
*
* @param {MapsModel} options Specifies the options
* @param {string | HTMLElement} element Specifies the element
*/
constructor(options?: MapsModel, element?: string | HTMLElement) {
super(options, <HTMLElement | string>element);
setValue('mergePersistData', this.mergePersistMapsData, this);
}
/**
* To manage persist maps data.
*
* @returns {void}
*/
private mergePersistMapsData(): void {
let data: string;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
let windowData: any;
try {
windowData = window.localStorage;
} catch (e) {
windowData = null;
}
if (!isNullOrUndefined(windowData)) {
data = window.localStorage.getItem(this.getModuleName() + this.element.id);
}
if (!(isNullOrUndefined(data) || (data === ''))) {
const dataObj: Maps = JSON.parse(data);
const keys: string[] = Object.keys(dataObj);
this.isProtectedOnChange = true;
for (const key of keys) {
if ((typeof this[key as string] === 'object') && !isNullOrUndefined(this[key as string])) {
extend(this[key as string], dataObj[key as string]);
} else {
this[key as string] = dataObj[key as string];
}
}
this.isProtectedOnChange = false;
}
}
/**
* Gets the localized label by locale keyword.
*
* @param {string} key - Specifies the key
* @returns {string} - Returns the string value
* @private
*/
public getLocalizedLabel(key: string): string {
return this.localeObject.getConstant(key);
}
/**
* Initializing pre-required values.
*
* @returns {void}
*/
protected preRender(): void {
this.isDevice = Browser.isDevice;
this.initPrivateVariable();
this.allowServerDataBinding = false;
this.unWireEVents();
this.wireEVents();
this.setCulture();
}
private renderElements(): void {
if (!this.isDestroyed) {
this.trigger(load, { maps: this });
this.createSVG();
this.findBaseAndSubLayers();
if (!isNullOrUndefined(this.markerModule) && this.markerModule.getMapsInstance()) {
this.markerModule.initializeMarkerClusterList();
}
this.createSecondaryElement();
this.addTabIndex();
this.themeStyle = getThemeStyle(this.theme);
this.renderBorder();
this.renderTitle(this.titleSettings, 'title', null, null);
this.renderArea();
this.processRequestJsonData();
this.renderComplete();
this.isAddLayer = !this.isTileMap ? false : this.isAddLayer;
}
}
/**
* To Initialize the control rendering.
*
* @returns {void}
*/
protected render(): void {
this.renderElements();
}
protected processRequestJsonData(): void {
const length: number = this.layersCollection.length - 1;
this.serverProcess = { request: 0, response: 0 }; let queryModule: Query;
let dataModule: DataManager;
Array.prototype.forEach.call(this.layersCollection, (layer: LayerSettings, layerIndex: number) => {
if (layer.shapeData instanceof DataManager) {
this.serverProcess['request']++;
dataModule = layer.shapeData;
queryModule = layer.query instanceof Query ? layer.query : new Query();
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const dataManager: Promise<any> = dataModule.executeQuery(queryModule);
// eslint-disable-next-line @typescript-eslint/no-explicit-any
dataManager.then((e: any) => {
this.processResponseJsonData('DataManager', e, layer, 'ShapeData');
});
} else if (layer.shapeData instanceof MapAjax || layer.shapeData) {
if (!isNullOrUndefined(layer.shapeData['dataOptions'])) {
this.processAjaxRequest(layer, layer.shapeData, 'ShapeData');
}
}
if (layer.dataSource instanceof DataManager) {
this.serverProcess['request']++;
dataModule = layer.dataSource as DataManager;
queryModule = layer.query instanceof Query ? layer.query : new Query();
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const dataManager: Promise<any> = dataModule.executeQuery(queryModule);
// eslint-disable-next-line @typescript-eslint/no-explicit-any
dataManager.then((e: any) => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
layer.dataSource = processResult(e) as any[];
});
}
if (layer.markerSettings.length > 0) {
for (let i: number = 0; i < layer.markerSettings.length; i++) {
if (layer.markerSettings[i as number].dataSource instanceof DataManager) {
this.serverProcess['request']++;
dataModule = layer.markerSettings[i as number].dataSource as DataManager;
queryModule = layer.markerSettings[i as number].query instanceof Query ?
layer.markerSettings[i as number].query : new Query();
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const dataManager: Promise<any> = dataModule.executeQuery(queryModule);
// eslint-disable-next-line @typescript-eslint/no-explicit-any
dataManager.then((e: any) => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
layer.markerSettings[i as number].dataSource = processResult(e) as any[];
});
}
}
}
if (layer.bubbleSettings.length > 0) {
for (let i: number = 0; i < layer.bubbleSettings.length; i++) {
if (layer.bubbleSettings[i as number].dataSource instanceof DataManager) {
this.serverProcess['request']++;
dataModule = layer.bubbleSettings[i as number].dataSource as DataManager;
queryModule = layer.bubbleSettings[i as number].query instanceof Query ?
layer.bubbleSettings[i as number].query : new Query();
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const dataManager: Promise<any> = dataModule.executeQuery(queryModule);
// eslint-disable-next-line @typescript-eslint/no-explicit-any
dataManager.then((e: any) => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
layer.bubbleSettings[i as number].dataSource = processResult(e) as any[];
});
}
}
}
if (layer.dataSource instanceof MapAjax || (!isNullOrUndefined(layer.dataSource) && !isNullOrUndefined(layer.dataSource['dataOptions']))) {
this.processAjaxRequest(layer, layer.dataSource, 'DataSource');
}
if (this.serverProcess['request'] === this.serverProcess['response'] && length === layerIndex) {
this.processResponseJsonData(null);
}
});
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
private processAjaxRequest(layer: LayerSettings, localAjax: MapAjax | any, type: string): void {
this.serverProcess['request']++;
const fetchApiModule: Fetch = new Fetch(localAjax.dataOptions, localAjax.type, localAjax.contentType);
// eslint-disable-next-line @typescript-eslint/no-explicit-any
fetchApiModule.onSuccess = (args: any) => {
if (!isNullOrUndefined(args.type) && args.type === 'application/octet-stream') {
const reader: FileReader = new FileReader();
//eslint-disable-next-line @typescript-eslint/no-this-alias
const map: Maps = this;
// eslint-disable-next-line @typescript-eslint/tslint/config
reader.onload = function () {
args = JSON.parse(reader.result.toString());
map.processResponseJsonData('Fetch', args, layer, type);
};
reader.readAsText(args);
} else {
this.processResponseJsonData('Fetch', args, layer, type);
}
};
fetchApiModule.send(localAjax.sendData);
}
/**
* This method is used to process the JSON data to render the maps.
*
* @param {string} processType - Specifies the process type in maps.
* @param {any | string} data - Specifies the data for maps.
* @param {LayerSettings} layer - Specifies the layer for the maps.
* @param {string} dataType - Specifies the data type for maps.
* @returns {void}
* @private
*/
public processResponseJsonData(processType: string,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
data?: any | string, layer?: LayerSettings, dataType?: string): void {
this.serverProcess['response']++;
if (processType) {
if (dataType === 'ShapeData') {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
layer.shapeData = (processType === 'DataManager') ? processResult((data as any)) : data;
} else {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
layer.dataSource = (processType === 'DataManager') ? processResult((data as any)) : data;
}
}
if (!isNullOrUndefined(processType) && this.serverProcess['request'] === this.serverProcess['response']) {
const collection: LayerSettings[] = this.layersCollection;
this.layersCollection = [];
for (let i: number = 0; i < collection.length; i++) {
if (collection[i as number].isBaseLayer) {
this.layersCollection.push(collection[i as number]);
}
}
for (let j: number = 0; j < collection.length; j++) {
if (!collection[j as number].isBaseLayer) {
this.layersCollection.push(collection[j as number]);
}
}
this.renderMap();
} else if (isNullOrUndefined(processType)) {
this.renderMap();
}
}
private renderMap(): void {
if (this.legendModule && this.legendSettings.visible) {
this.legendModule.renderLegend();
}
this.createTile();
if (this.zoomSettings.enable && this.zoomModule) {
this.zoomModule.createZoomingToolbars();
}
if (!isNullOrUndefined(this.dataLabelModule)) {
this.dataLabelModule.dataLabelCollections = [];
}
this.mapLayerPanel.measureLayerPanel();
if (!isNullOrUndefined(this.svgObject)) {
this.element.appendChild(this.svgObject);
}
this.setSecondaryElementPosition();
for (let i: number = 0; i < this.layers.length; i++) {
if (this.layers[i as number].selectionSettings && this.layers[i as number].selectionSettings.enable &&
this.layers[i as number].initialShapeSelection.length > 0 && this.checkInitialRender) {
const checkSelection: boolean = this.layers[i as number].selectionSettings.enableMultiSelect;
this.layers[i as number].selectionSettings.enableMultiSelect = checkSelection ? checkSelection : true;
const shapeSelection: InitialShapeSelectionSettingsModel[] = this.layers[i as number].initialShapeSelection;
for (let j: number = 0; j < this.layers[i as number].initialShapeSelection.length; j++) {
this.shapeSelection(i, shapeSelection[j as number].shapePath, shapeSelection[j as number].shapeValue, true);
}
this.layers[i as number].selectionSettings.enableMultiSelect = checkSelection;
if (i === this.layers.length - 1) { this.checkInitialRender = false; }
}
if (!this.isResize) {
for (let k: number = 0; k < this.layers[i as number].markerSettings.length; k++) {
// eslint-disable-next-line max-len
if (this.layers[i as number].markerSettings[k as number].selectionSettings && this.layers[i as number].markerSettings[k as number].selectionSettings.enable
&& this.layers[i as number].markerSettings[k as number].initialMarkerSelection.length > 0) {
const markerSelectionValues: InitialMarkerSelectionSettingsModel[] =
this.layers[i as number].markerSettings[k as number].initialMarkerSelection;
for (let j: number = 0; j < markerSelectionValues.length; j++) {
this.markerInitialSelection(i, k, this.layers[i as number].markerSettings[k as number],
markerSelectionValues[j as number].latitude,
markerSelectionValues[j as number].longitude);
}
}
}
}
}
if (!isNullOrUndefined(document.getElementById(this.element.id + '_tile_parent'))) {
const svg: ClientRect = this.svgObject.getBoundingClientRect();
const element: HTMLElement = document.getElementById(this.element.id);
const tileElement: HTMLElement = document.getElementById(this.element.id + '_tile_parent');
const tileElement1: HTMLElement = document.getElementById(this.element.id + '_tiles');
const tile: ClientRect = tileElement.getBoundingClientRect();
let top: number; let left: number;
left = parseFloat(tileElement.style.left);
const bottom: number = svg.bottom - tile.bottom - element.offsetTop;
top = parseFloat(tileElement.style.top);
top = (bottom <= 11) ? top : (!isNullOrUndefined(this.legendModule) && this.legendSettings.position === 'Bottom') ? this.mapAreaRect.y : (top * 2);
left = (bottom <= 11) ? left : !isNullOrUndefined(this.legendModule) ? left : (left * 2);
tileElement.style.top = top + 'px';
tileElement.style.left = left + 'px';
tileElement1.style.top = top + 'px';
tileElement1.style.left = left + 'px';
if (!isNullOrUndefined(this.legendModule) && this.legendModule.totalPages.length > 0) {
tileElement.style.height = tileElement1.style.height = this.legendModule.legendTotalRect.height + 'px';
tileElement.style.width = tileElement1.style.width = this.legendModule.legendTotalRect.width + 'px';
}
}
this.arrangeTemplate();
if (this.annotationsModule) {
if (this.width !== '0px' && this.height !== '0px' && this.width !== '0%' && this.height !== '0%') {
this.annotationsModule.renderAnnotationElements();
}
}
this.element.style.outline = 'none';
this.element.style.position = 'relative';
for (let i: number = 0; i < document.getElementsByTagName('path').length - 1; i++) {
if (document.getElementsByTagName('path')[i as number].id.indexOf('shapeIndex') > -1) {
document.getElementsByTagName('path')[i as number].style.outline = 'none';
}
}
this.zoomingChange();
if (this.zoomModule && this.isDevice) {
this.zoomModule.removeToolbarOpacity(this.isTileMap ? Math.round(this.tileZoomLevel) : this.mapScaleValue, this.element.id + '_Zooming_');
}
if (!this.isZoomByPosition && !this.zoomNotApplied) {
this.triggerZoomEvent();
}
this.isResize = false;
}
private triggerZoomEvent(): void {
let loadedArgs: ILoadedEventArgs;
const minMaxLatitudeLongitude: IMinMaxLatitudeLongitude = this.getMinMaxLatitudeLongitude();
// eslint-disable-next-line prefer-const
loadedArgs = {
maps: this, isResized: this.isResize, minLatitude: minMaxLatitudeLongitude.minLatitude,
maxLatitude: minMaxLatitudeLongitude.maxLatitude, minLongitude: minMaxLatitudeLongitude.minLongitude,
maxLongitude: minMaxLatitudeLongitude.maxLongitude, cancel: false, name: 'Loaded'
};
this.trigger('loaded', loadedArgs);
//eslint-enable @typescript-eslint/prefer-const
}
/**
* To apply color to the initial selected marker.
*
* @param {SelectionSettingsModel} selectionSettings - Specifies the selection settings
* @param {Maps} map - Specifies the instance of the maps
* @param {Element} targetElement - Specifies the target element
* @param {object} data - Specifies the data
* @returns {void}
* @private
*/
public markerSelection(
selectionSettings: SelectionSettingsModel, map: Maps, targetElement: Element,
data: object
): void {
const border: BorderModel = {
color: selectionSettings.border.color,
width: selectionSettings.border.width / map.scale,
opacity: selectionSettings.border.opacity
};
const markerSelectionProperties: object = {
opacity: selectionSettings.opacity,
fill: selectionSettings.fill,
border: border,
target: targetElement.id,
cancel: false,
data: data,
maps: map
};
if (!getElement('MarkerselectionMap')) {
document.body.appendChild(createStyle('MarkerselectionMap', 'MarkerselectionMapStyle', markerSelectionProperties));
} else {
customizeStyle('MarkerselectionMap', 'MarkerselectionMapStyle', markerSelectionProperties);
}
if (this.selectedMarkerElementId.length === 0 || selectionSettings.enableMultiSelect) {
if (targetElement.tagName === 'g') {
targetElement.children[0].setAttribute('class', 'MarkerselectionMapStyle');
this.selectedMarkerElementId.push(targetElement.children[0].id);
} else {
targetElement.setAttribute('class', 'MarkerselectionMapStyle');
this.selectedMarkerElementId.push(targetElement.id);
}
}
}
/**
* initial selection of marker.
*
* @param {number} layerIndex - Specifies the layer index
* @param {number} markerIndex - Specifies the marker index
* @param {MarkerSettingsModel} markerSettings - Specifies the marker settings
* @param {number} latitude - Specifies hte latitude
* @param {number} longitude - Specifies the longitude
* @returns {void}
* @private
*/
public markerInitialSelection(
layerIndex: number, markerIndex: number, markerSettings: MarkerSettingsModel,
latitude: number, longitude: number
): void {
const selectionSettings: SelectionSettingsModel = markerSettings.selectionSettings;
if (selectionSettings.enable) {
for (let i: number = 0; i < markerSettings.dataSource['length']; i++) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const data: any = markerSettings.dataSource[i as number];
if (data['latitude'] === latitude && data['longitude'] === longitude) {
const targetId: string = this.element.id + '_' + 'LayerIndex_' + layerIndex + '_MarkerIndex_' + markerIndex +
'_dataIndex_' + i;
this.markerSelection(selectionSettings, this, getElement(targetId), data);
}
}
}
}
/**
* Render the map area border.
*
* @returns {void}
*/
private renderArea(): void {
const width: number = this.mapsArea.border.width;
const background: string = this.mapsArea.background;
if (width > 0 || (background || this.themeStyle.areaBackgroundColor)) {
const mapBorder: BorderModel = {
opacity: isNullOrUndefined(this.mapsArea.border.opacity) ? 1 : this.mapsArea.border.opacity,
color: this.mapsArea.border.color, width: this.mapsArea.border.width
};
const rect: RectOption = new RectOption(
this.element.id + '_MapAreaBorder', background || this.themeStyle.areaBackgroundColor,
mapBorder, 1, this.mapAreaRect
);
this.svgObject.appendChild(this.renderer.drawRectangle(rect) as SVGRectElement);
}
}
/**
* To add tab index for map element.
*
* @returns {void}
*/
private addTabIndex(): void {
this.element.setAttribute('aria-label', this.description || 'Maps Element');
this.element.setAttribute('role', 'region');
this.element.tabIndex = this.tabIndex;
}
private setSecondaryElementPosition(): void {
const element: HTMLDivElement = getElementByID(this.element.id + '_Secondary_Element') as HTMLDivElement;
const rect: ClientRect = this.element.getBoundingClientRect();
const svgElement: Element = getElementByID(this.element.id + '_svg');
if (!isNullOrUndefined(svgElement)) {
const svgRect: ClientRect = svgElement.getBoundingClientRect();
element.style.left = Math.max(svgRect.left - rect.left, 0) + 'px';
element.style.top = Math.max(svgRect.top - rect.top, 0) + 'px';
}
}
private zoomingChange(): void {
let left: number; let top: number;
if (getElementByID(this.element.id + '_Layer_Collections') && this.zoomModule) {
this.zoomModule.layerCollectionEle = getElementByID(this.element.id + '_Layer_Collections');
}
if (this.isTileMap && getElementByID(this.element.id + '_Tile_SVG') && getElementByID(this.element.id + '_tile_parent')) {
const tileElement: Element = getElementByID(this.element.id + '_tile_parent');
const tileSvgElement: Element = getElementByID(this.element.id + '_Tile_SVG');
const tileSvgParentElement: Element = getElementByID(this.element.id + '_Tile_SVG_Parent');
const tileRect: ClientRect = tileElement.getBoundingClientRect();
const tileSvgRect: ClientRect = tileSvgElement.getBoundingClientRect();
left = (tileRect.left - tileSvgRect.left);
top = (tileRect.top - tileSvgRect.top);
(tileSvgParentElement as HTMLElement).style.left = left + 'px';
(tileSvgParentElement as HTMLElement).style.top = top + 'px';
if (!isNullOrUndefined(this.le