UNPKG

devextreme

Version:

HTML5 JavaScript Component Suite for Responsive Web Development

407 lines (406 loc) • 15.9 kB
/** * DevExtreme (esm/ui/map/provider.dynamic.bing.js) * Version: 21.1.4 * Build date: Mon Jun 21 2021 * * Copyright (c) 2012 - 2021 Developer Express Inc. ALL RIGHTS RESERVED * Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/ */ import { noop } from "../../core/utils/common"; import { getWindow } from "../../core/utils/window"; var window = getWindow(); import Promise from "../../core/polyfills/promise"; import { extend } from "../../core/utils/extend"; import errors from "../widget/ui.errors"; import { map, each } from "../../core/utils/iterator"; import DynamicProvider from "./provider.dynamic"; import Color from "../../color"; import ajax from "../../core/utils/ajax"; import { isDefined } from "../../core/utils/type"; var BING_MAP_READY = "_bingScriptReady"; var BING_URL_V8 = "https://www.bing.com/api/maps/mapcontrol?callback=" + BING_MAP_READY; var INFOBOX_V_OFFSET_V8 = 13; var BING_CREDENTIALS = "AhuxC0dQ1DBTNo8L-H9ToVMQStmizZzBJdraTSgCzDSWPsA1Qd8uIvFSflzxdaLH"; var MIN_LOCATION_RECT_LENGTH = 1e-16; var msMapsLoaded = function() { return window.Microsoft && window.Microsoft.Maps }; var msMapsLoader; var BingProvider = DynamicProvider.inherit({ _mapType: function(type) { var mapTypes = { roadmap: Microsoft.Maps.MapTypeId.road, hybrid: Microsoft.Maps.MapTypeId.aerial, satellite: Microsoft.Maps.MapTypeId.aerial }; return mapTypes[type] || mapTypes.road }, _movementMode: function(type) { var movementTypes = { driving: Microsoft.Maps.Directions.RouteMode.driving, walking: Microsoft.Maps.Directions.RouteMode.walking }; return movementTypes[type] || movementTypes.driving }, _resolveLocation: function(location) { return new Promise(function(resolve) { var latLng = this._getLatLng(location); if (latLng) { resolve(new Microsoft.Maps.Location(latLng.lat, latLng.lng)) } else { this._geocodeLocation(location).then((function(geocodedLocation) { resolve(geocodedLocation) })) } }.bind(this)) }, _geocodedLocations: {}, _geocodeLocationImpl: function(location) { return new Promise(function(resolve) { if (!isDefined(location)) { resolve(new Microsoft.Maps.Location(0, 0)); return } var searchManager = new Microsoft.Maps.Search.SearchManager(this._map); var searchRequest = { where: location, count: 1, callback: function(searchResponse) { var result = searchResponse.results[0]; if (result) { var boundsBox = searchResponse.results[0].location; resolve(new Microsoft.Maps.Location(boundsBox.latitude, boundsBox.longitude)) } else { resolve(new Microsoft.Maps.Location(0, 0)) } } }; searchManager.geocode(searchRequest) }.bind(this)) }, _normalizeLocation: function(location) { return { lat: location.latitude, lng: location.longitude } }, _normalizeLocationRect: function(locationRect) { var northWest = this._normalizeLocation(locationRect.getNorthwest()); var southEast = this._normalizeLocation(locationRect.getSoutheast()); return { northEast: { lat: northWest.lat, lng: southEast.lng }, southWest: { lat: southEast.lat, lng: northWest.lng } } }, _loadImpl: function() { return new Promise(function(resolve) { if (msMapsLoaded()) { resolve() } else { if (!msMapsLoader) { msMapsLoader = this._loadMapScript() } msMapsLoader.then(function() { if (msMapsLoaded()) { resolve(); return } this._loadMapScript().then(resolve) }.bind(this)) } }.bind(this)).then((function() { return Promise.all([new Promise((function(resolve) { Microsoft.Maps.loadModule("Microsoft.Maps.Search", { callback: resolve }) })), new Promise((function(resolve) { Microsoft.Maps.loadModule("Microsoft.Maps.Directions", { callback: resolve }) }))]) })) }, _loadMapScript: function() { return new Promise((function(resolve) { window[BING_MAP_READY] = resolve; ajax.sendRequest({ url: BING_URL_V8, dataType: "script" }) })).then((function() { try { delete window[BING_MAP_READY] } catch (e) { window[BING_MAP_READY] = void 0 } })) }, _init: function() { this._createMap(); return Promise.resolve() }, _createMap: function() { var controls = this._option("controls"); this._map = new Microsoft.Maps.Map(this._$container[0], { credentials: this._keyOption("bing") || BING_CREDENTIALS, zoom: this._option("zoom"), showDashboard: controls, showMapTypeSelector: controls, showScalebar: controls }) }, _attachHandlers: function() { this._providerViewChangeHandler = Microsoft.Maps.Events.addHandler(this._map, "viewchange", this._viewChangeHandler.bind(this)); this._providerClickHandler = Microsoft.Maps.Events.addHandler(this._map, "click", this._clickActionHandler.bind(this)) }, _viewChangeHandler: function() { var bounds = this._map.getBounds(); this._option("bounds", this._normalizeLocationRect(bounds)); var center = this._map.getCenter(); this._option("center", this._normalizeLocation(center)); if (!this._preventZoomChangeEvent) { this._option("zoom", this._map.getZoom()) } }, _clickActionHandler: function(e) { if ("map" === e.targetType) { this._fireClickAction({ location: this._normalizeLocation(e.location) }) } }, updateDimensions: function() { var $container = this._$container; this._map.setOptions({ width: $container.width(), height: $container.height() }); return Promise.resolve() }, updateMapType: function() { var type = this._option("type"); var labelOverlay = Microsoft.Maps.LabelOverlay; this._map.setView({ animate: false, mapTypeId: this._mapType(type), labelOverlay: "satellite" === type ? labelOverlay.hidden : labelOverlay.visible }); return Promise.resolve() }, updateBounds: function() { return Promise.all([this._resolveLocation(this._option("bounds.northEast")), this._resolveLocation(this._option("bounds.southWest"))]).then(function(result) { var bounds = new Microsoft.Maps.LocationRect.fromLocations(result[0], result[1]); this._map.setView({ animate: false, bounds: bounds }) }.bind(this)) }, updateCenter: function() { return this._resolveLocation(this._option("center")).then(function(center) { this._map.setView({ animate: false, center: center }) }.bind(this)) }, updateZoom: function() { this._map.setView({ animate: false, zoom: this._option("zoom") }); return Promise.resolve() }, updateControls: function() { this.clean(); return this.render.apply(this, arguments) }, _renderMarker: function(options) { return this._resolveLocation(options.location).then(function(location) { var pushpinOptions = { icon: options.iconSrc || this._option("markerIconSrc") }; if (options.html) { extend(pushpinOptions, { htmlContent: options.html, width: null, height: null }); var htmlOffset = options.htmlOffset; if (htmlOffset) { pushpinOptions.anchor = new Microsoft.Maps.Point(-htmlOffset.left, -htmlOffset.top) } } var pushpin = new Microsoft.Maps.Pushpin(location, pushpinOptions); this._map.entities.push(pushpin); var infobox = this._renderTooltip(location, options.tooltip); var handler; if (options.onClick || options.tooltip) { var markerClickAction = this._mapWidget._createAction(options.onClick || noop); var markerNormalizedLocation = this._normalizeLocation(location); handler = Microsoft.Maps.Events.addHandler(pushpin, "click", (function() { markerClickAction({ location: markerNormalizedLocation }); if (infobox) { infobox.setOptions({ visible: true }) } })) } return { location: location, marker: pushpin, infobox: infobox, handler: handler } }.bind(this)) }, _renderTooltip: function(location, options) { if (!options) { return } options = this._parseTooltipOptions(options); var infobox = new Microsoft.Maps.Infobox(location, { description: options.text, offset: new Microsoft.Maps.Point(0, INFOBOX_V_OFFSET_V8), visible: options.visible }); infobox.setMap(this._map); return infobox }, _destroyMarker: function(marker) { this._map.entities.remove(marker.marker); if (marker.infobox) { marker.infobox.setMap(null) } if (marker.handler) { Microsoft.Maps.Events.removeHandler(marker.handler) } }, _renderRoute: function(options) { return Promise.all(map(options.locations, function(point) { return this._resolveLocation(point) }.bind(this))).then(function(locations) { return new Promise(function(resolve) { var direction = new Microsoft.Maps.Directions.DirectionsManager(this._map); var color = new Color(options.color || this._defaultRouteColor()).toHex(); var routeColor = new Microsoft.Maps.Color.fromHex(color); routeColor.a = 255 * (options.opacity || this._defaultRouteOpacity()); direction.setRenderOptions({ autoUpdateMapView: false, displayRouteSelector: false, waypointPushpinOptions: { visible: false }, drivingPolylineOptions: { strokeColor: routeColor, strokeThickness: options.weight || this._defaultRouteWeight() }, walkingPolylineOptions: { strokeColor: routeColor, strokeThickness: options.weight || this._defaultRouteWeight() } }); direction.setRequestOptions({ routeMode: this._movementMode(options.mode), routeDraggable: false }); each(locations, (function(_, location) { var waypoint = new Microsoft.Maps.Directions.Waypoint({ location: location }); direction.addWaypoint(waypoint) })); var directionHandlers = []; directionHandlers.push(Microsoft.Maps.Events.addHandler(direction, "directionsUpdated", (function(args) { while (directionHandlers.length) { Microsoft.Maps.Events.removeHandler(directionHandlers.pop()) } var routeSummary = args.routeSummary[0]; resolve({ instance: direction, northEast: routeSummary.northEast, southWest: routeSummary.southWest }) }))); directionHandlers.push(Microsoft.Maps.Events.addHandler(direction, "directionsError", (function(args) { while (directionHandlers.length) { Microsoft.Maps.Events.removeHandler(directionHandlers.pop()) } var status = "RouteResponseCode: " + args.responseCode + " - " + args.message; errors.log("W1006", status); resolve({ instance: direction }) }))); direction.calculateDirections() }.bind(this)) }.bind(this)) }, _destroyRoute: function(routeObject) { routeObject.instance.dispose() }, _fitBounds: function() { this._updateBounds(); if (this._bounds && this._option("autoAdjust")) { var zoomBeforeFitting = this._map.getZoom(); this._preventZoomChangeEvent = true; var bounds = this._bounds.clone(); bounds.height = 1.1 * bounds.height; bounds.width = 1.1 * bounds.width; this._map.setView({ animate: false, bounds: bounds, zoom: zoomBeforeFitting }); var zoomAfterFitting = this._map.getZoom(); if (zoomBeforeFitting < zoomAfterFitting) { this._map.setView({ animate: false, zoom: zoomBeforeFitting }) } else { this._option("zoom", zoomAfterFitting) } delete this._preventZoomChangeEvent } return Promise.resolve() }, _extendBounds: function(location) { if (this._bounds) { this._bounds = new Microsoft.Maps.LocationRect.fromLocations(this._bounds.getNorthwest(), this._bounds.getSoutheast(), location) } else { this._bounds = new Microsoft.Maps.LocationRect(location, MIN_LOCATION_RECT_LENGTH, MIN_LOCATION_RECT_LENGTH) } }, clean: function() { if (this._map) { Microsoft.Maps.Events.removeHandler(this._providerViewChangeHandler); Microsoft.Maps.Events.removeHandler(this._providerClickHandler); this._clearMarkers(); this._clearRoutes(); this._map.dispose() } return Promise.resolve() } }); export default BingProvider;