1569 lines
46 KiB
JavaScript
Executable File
1569 lines
46 KiB
JavaScript
Executable File
/**
|
|
* Class trackdirect.models.Map
|
|
* @see https://developers.google.com/maps/documentation/javascript/reference#Map
|
|
* @param {string} mapElementId
|
|
* @param {object} options
|
|
*/
|
|
trackdirect.models.Map = function (mapElementId, options) {
|
|
this._init(mapElementId, options);
|
|
|
|
// Call the parent constructor
|
|
if (typeof google === "object" && typeof google.maps === "object") {
|
|
google.maps.Map.call(
|
|
this,
|
|
document.getElementById(mapElementId),
|
|
this._getGoolgeMapOptions()
|
|
);
|
|
} else if (typeof L === "object") {
|
|
L.Map.call(
|
|
this,
|
|
document.getElementById(mapElementId),
|
|
this._getLeafletMapOptions()
|
|
);
|
|
this._updateLeafletTileLayer();
|
|
L.control
|
|
.zoom({
|
|
position: "bottomright",
|
|
})
|
|
.addTo(this);
|
|
}
|
|
|
|
this._initMap();
|
|
};
|
|
if (typeof google === "object" && typeof google.maps === "object") {
|
|
trackdirect.models.Map.prototype = Object.create(google.maps.Map.prototype);
|
|
} else if (typeof L === "object") {
|
|
trackdirect.models.Map.prototype = Object.create(L.Map.prototype);
|
|
}
|
|
trackdirect.models.Map.prototype.constructor = trackdirect.models.Map;
|
|
|
|
/**
|
|
* Init
|
|
*/
|
|
trackdirect.models.Map.prototype._init = function (mapElementId, options) {
|
|
this._mapElementId = mapElementId;
|
|
this._tdMapOptions = options;
|
|
this._initBasic();
|
|
this._initMapTypes();
|
|
};
|
|
|
|
/**
|
|
* Init basic stuff
|
|
*/
|
|
trackdirect.models.Map.prototype._initBasic = function () {
|
|
this._tdEventListeners = {};
|
|
this._tdEventTimeout = null;
|
|
this._currentContentZoom = null;
|
|
this._visibleMapSectors = [];
|
|
this._newMarkersToShow = [];
|
|
|
|
this._leafletTileLayer = null;
|
|
this._heatMap = null;
|
|
|
|
// Init public variables
|
|
this.markerCollection = new trackdirect.models.MarkerCollection();
|
|
this.state = new trackdirect.models.MapState();
|
|
};
|
|
|
|
/**
|
|
* Init map types
|
|
*/
|
|
trackdirect.models.Map.prototype._initMapTypes = function () {
|
|
this._supportedMapTypes = {};
|
|
if (
|
|
typeof this._tdMapOptions.supportedMapTypes !== "undefined" &&
|
|
this._tdMapOptions.supportedMapTypes !== null &&
|
|
Object.keys(this._tdMapOptions.supportedMapTypes).length > 0
|
|
) {
|
|
this._supportedMapTypes = this._tdMapOptions.supportedMapTypes;
|
|
} else if (typeof google === "object" && typeof google.maps === "object") {
|
|
this._supportedMapTypes["roadmap"] = google.maps.MapTypeId.ROADMAP;
|
|
this._supportedMapTypes["terrain"] = google.maps.MapTypeId.TERRAIN;
|
|
this._supportedMapTypes["satellite"] = google.maps.MapTypeId.SATELLITE;
|
|
this._supportedMapTypes["hybrid"] = google.maps.MapTypeId.HYBRID;
|
|
} else if (typeof L === "object") {
|
|
this._supportedMapTypes["roadmap"] = "OpenStreetMap.Mapnik";
|
|
this._supportedMapTypes["terrain"] = "OpenTopoMap";
|
|
}
|
|
|
|
if (
|
|
typeof this._tdMapOptions.maptype !== "undefined" &&
|
|
this._tdMapOptions.maptype !== null &&
|
|
this._tdMapOptions.maptype in this._supportedMapTypes
|
|
) {
|
|
this._mapType = this._tdMapOptions.maptype;
|
|
} else {
|
|
this._mapType = Object.keys(this._supportedMapTypes)[0];
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Init the map
|
|
*/
|
|
trackdirect.models.Map.prototype._initMap = function () {
|
|
this._heatMap = new trackdirect.models.HeatMap(this);
|
|
this._setMapInitialLocation();
|
|
this._initOms();
|
|
this._initInfoWindowEvent();
|
|
this._updateMapContent();
|
|
this._initMapEvents();
|
|
|
|
// create kmlLayer object from URL
|
|
if (typeof google === "object" && typeof google.maps === "object") {
|
|
if (typeof this._tdMapOptions.mid !== "undefined") {
|
|
var kmlUrl =
|
|
"https://www.google.com/maps/d/u/0/kml?mid=" + this._tdMapOptions.mid;
|
|
var kmlLayer = new google.maps.KmlLayer(kmlUrl, { map: this });
|
|
}
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Trigger a resize event
|
|
*/
|
|
trackdirect.models.Map.prototype.triggerResize = function () {
|
|
if (typeof google === "object" && typeof google.maps === "object") {
|
|
google.maps.event.trigger(this, "resize");
|
|
} else if (typeof L === "object") {
|
|
L.Map.prototype._onResize.call(this);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Set Map center
|
|
* @param {LatLngLiteral} pos
|
|
* @param {int} zoom
|
|
*/
|
|
trackdirect.models.Map.prototype.setCenter = function (pos, zoom) {
|
|
if (typeof google === "object" && typeof google.maps === "object") {
|
|
google.maps.Map.prototype.setCenter.call(this, pos);
|
|
if (typeof zoom !== "undefined") {
|
|
google.maps.Map.prototype.setZoom.call(this, zoom);
|
|
}
|
|
} else if (typeof L === "object") {
|
|
zoom = typeof zoom !== "undefined" ? zoom : this.getZoom();
|
|
L.Map.prototype.setView.call(this, pos, zoom);
|
|
}
|
|
this._renderCordinatesContainer(pos);
|
|
};
|
|
|
|
/**
|
|
* Get Map center literal
|
|
* @return LatLngLiteral
|
|
*/
|
|
trackdirect.models.Map.prototype.getCenterLiteral = function () {
|
|
if (typeof google === "object" && typeof google.maps === "object") {
|
|
var latLng = google.maps.Map.prototype.getCenter.call(this);
|
|
if (typeof latLng !== "undefined" && typeof latLng.lat === "function") {
|
|
return { lat: latLng.lat(), lng: latLng.lng() };
|
|
} else {
|
|
return latLng;
|
|
}
|
|
} else if (typeof L === "object") {
|
|
var latLng = L.Map.prototype.getCenter.call(this);
|
|
if (typeof latLng !== "undefined") {
|
|
return { lat: latLng.lat, lng: latLng.lng };
|
|
} else {
|
|
return latLng;
|
|
}
|
|
}
|
|
return null;
|
|
};
|
|
|
|
/**
|
|
* Fit bounds
|
|
* @param {Array} bounds
|
|
*/
|
|
trackdirect.models.Map.prototype.fitBounds = function (bounds) {
|
|
if (typeof google === "object" && typeof google.maps === "object") {
|
|
var latLngBounds = new google.maps.LatLngBounds();
|
|
for (var i = 0; i < bounds.length; i++) {
|
|
latLngBounds.extend(bounds[i]);
|
|
}
|
|
google.maps.Map.prototype.fitBounds.call(this, latLngBounds);
|
|
} else if (typeof L === "object") {
|
|
L.Map.prototype.fitBounds.call(this, bounds);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* set Map center by station position
|
|
* @param {LatLngLiteral} pos
|
|
*/
|
|
trackdirect.models.Map.prototype.setCenterByStationId = function (stationId) {
|
|
var latestVisibleMarker =
|
|
this.markerCollection.getStationLatestVisibleMarker(stationId);
|
|
if (latestVisibleMarker !== null) {
|
|
this.setCenter(latestVisibleMarker.packet.getLatLngLiteral());
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Get map DOM element id
|
|
* @return {string}
|
|
*/
|
|
trackdirect.models.Map.prototype.getMapElementId = function () {
|
|
return this._mapElementId;
|
|
};
|
|
|
|
/**
|
|
* Get map options
|
|
* @return {object}
|
|
*/
|
|
trackdirect.models.Map.prototype.getTdMapOptions = function () {
|
|
return this._tdMapOptions;
|
|
};
|
|
|
|
/**
|
|
* Returns true if specified map sector is visible
|
|
* If we are filtering we consider all mapsectors visible
|
|
* @param {int} mapSector
|
|
* @return {boolean}
|
|
*/
|
|
trackdirect.models.Map.prototype.isMapSectorVisible = function (mapSector) {
|
|
if (
|
|
this._visibleMapSectors.indexOf(mapSector) >= 0 ||
|
|
this.state.isFilterMode
|
|
) {
|
|
return true;
|
|
}
|
|
return false;
|
|
};
|
|
|
|
/**
|
|
* Returnes the number of new markers in queue
|
|
* @return {int}
|
|
*/
|
|
trackdirect.models.Map.prototype.getNumberOfNewMarkersToShow = function () {
|
|
return this._newMarkersToShow;
|
|
};
|
|
|
|
/**
|
|
* Show all markers that has recently been added
|
|
* @param {boolean} track
|
|
*/
|
|
trackdirect.models.Map.prototype.showNewMarkersInQueue = function (track) {
|
|
track = typeof track !== "undefined" ? track : true;
|
|
|
|
var oldestAllowedTrackingTimestamp = 0;
|
|
if (this.state.onlyTrackRecentPackets) {
|
|
oldestAllowedTrackingTimestamp = Math.floor(Date.now() / 1000) - 60;
|
|
}
|
|
|
|
while ((markerIdKey = this._newMarkersToShow.pop()) != null) {
|
|
if (!this.markerCollection.isExistingMarker(markerIdKey)) {
|
|
continue;
|
|
}
|
|
var marker = this.markerCollection.getMarker(markerIdKey);
|
|
trackdirect.services.callbackExecutor.addWithPriority(
|
|
marker,
|
|
marker.showCompleteMarker,
|
|
[]
|
|
);
|
|
|
|
// Track
|
|
if (track && marker.packet.packet_order_id == 1) {
|
|
if (
|
|
marker.shouldMarkerBeVisible() &&
|
|
marker.showAsMarker &&
|
|
this.state.trackStationId !== null &&
|
|
this.state.trackStationId == marker.packet.station_id &&
|
|
this.state.getClientTimestamp(marker.packet.timestamp) >
|
|
oldestAllowedTrackingTimestamp
|
|
) {
|
|
trackdirect.services.callbackExecutor.addWithPriority(
|
|
this,
|
|
this.setCenterByStationId,
|
|
[marker.packet.station_id]
|
|
);
|
|
}
|
|
}
|
|
|
|
// Open previoulsy open info window
|
|
if (
|
|
this.state.openInfoWindowForMarkerIdKey !== null &&
|
|
this.state.openInfoWindowForMarkerIdKey == markerIdKey &&
|
|
marker.packet.packet_order_id == 1 &&
|
|
marker.shouldMarkerBeVisible() &&
|
|
marker.showAsMarker
|
|
) {
|
|
trackdirect.services.callbackExecutor.addWithPriority(
|
|
this,
|
|
this.openLatestStationInfoWindow,
|
|
[marker.packet.station_id]
|
|
);
|
|
}
|
|
}
|
|
this.state.openInfoWindowForMarkerIdKey = null;
|
|
};
|
|
|
|
/**
|
|
* Activate filtered mode
|
|
*/
|
|
trackdirect.models.Map.prototype.activateFilteredMode = function () {
|
|
this.state.isFilterMode = true;
|
|
this._deactivateHeatMap();
|
|
this._updateMapContent();
|
|
};
|
|
|
|
/**
|
|
* Deactivate filtered mode
|
|
*/
|
|
trackdirect.models.Map.prototype.deactivateFilteredMode = function () {
|
|
if (this.state.isFilterMode) {
|
|
this._activateHeatMap();
|
|
this.state.isFilterMode = false;
|
|
this.state.filterStationIds = [];
|
|
this._updateMapContent();
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Get the north east latitude of the current map view
|
|
* @return {float}
|
|
*/
|
|
trackdirect.models.Map.prototype.getNorthEastLat = function () {
|
|
if (this.getBounds() != null) {
|
|
if (typeof google === "object" && typeof google.maps === "object") {
|
|
return this.getBounds().getNorthEast().lat();
|
|
} else if (typeof L === "object") {
|
|
return this.getBounds().getNorthEast().lat;
|
|
}
|
|
}
|
|
return 0;
|
|
};
|
|
|
|
/**
|
|
* Get the north east longtitue of the current map view
|
|
* @return {float}
|
|
*/
|
|
trackdirect.models.Map.prototype.getNorthEastLng = function () {
|
|
if (this.getBounds() != null) {
|
|
if (typeof google === "object" && typeof google.maps === "object") {
|
|
return this.getBounds().getNorthEast().lng();
|
|
} else if (typeof L === "object") {
|
|
return this.getBounds().getNorthEast().lng;
|
|
}
|
|
}
|
|
return 0;
|
|
};
|
|
|
|
/**
|
|
* Get the south west latitude of the current map view
|
|
* @return {float}
|
|
*/
|
|
trackdirect.models.Map.prototype.getSouthWestLat = function () {
|
|
if (this.getBounds() != null) {
|
|
if (typeof google === "object" && typeof google.maps === "object") {
|
|
return this.getBounds().getSouthWest().lat();
|
|
} else if (typeof L === "object") {
|
|
return this.getBounds().getSouthWest().lat;
|
|
}
|
|
}
|
|
return 0;
|
|
};
|
|
|
|
/**
|
|
* Get the south west longitude of the current map view
|
|
* @return {float}
|
|
*/
|
|
trackdirect.models.Map.prototype.getSouthWestLng = function () {
|
|
if (this.getBounds() != null) {
|
|
if (typeof google === "object" && typeof google.maps === "object") {
|
|
return this.getBounds().getSouthWest().lng();
|
|
} else if (typeof L === "object") {
|
|
return this.getBounds().getSouthWest().lng;
|
|
}
|
|
}
|
|
return 0;
|
|
};
|
|
|
|
/**
|
|
* Returns true if map is ready
|
|
* @return {boolean}
|
|
*/
|
|
trackdirect.models.Map.prototype.isMapReady = function () {
|
|
if (this.getBounds() != null) {
|
|
return true;
|
|
}
|
|
return false;
|
|
};
|
|
|
|
/**
|
|
* Set map type
|
|
* @param {string} mapType
|
|
*/
|
|
trackdirect.models.Map.prototype.setMapType = function (mapType) {
|
|
if (mapType in this._supportedMapTypes) {
|
|
this._mapType = mapType;
|
|
if (typeof google === "object" && typeof google.maps === "object") {
|
|
this._updateGoogleMapTileLayer();
|
|
} else if (typeof L === "object") {
|
|
this._updateLeafletTileLayer();
|
|
}
|
|
this._emitTdEventListeners("change");
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Get map type
|
|
* @return {string}
|
|
*/
|
|
trackdirect.models.Map.prototype.getMapType = function () {
|
|
return this._mapType;
|
|
};
|
|
|
|
/**
|
|
* Get leaflet tile layer
|
|
* @return {string}
|
|
*/
|
|
trackdirect.models.Map.prototype.getLeafletTileLayer = function () {
|
|
return this._leafletTileLayer;
|
|
};
|
|
|
|
/**
|
|
* Returns current mid
|
|
* @return {String}
|
|
*/
|
|
trackdirect.models.Map.prototype.getMid = function () {
|
|
if (typeof this._tdMapOptions.mid !== "undefined") {
|
|
return this._tdMapOptions.mid;
|
|
}
|
|
return null;
|
|
};
|
|
|
|
/**
|
|
* Reset all markers, this will remove everything from map and memory
|
|
*/
|
|
trackdirect.models.Map.prototype.resetAllMarkers = function () {
|
|
while (this.markerCollection.getNumberOfMarkers() > 0) {
|
|
var i = this.markerCollection.getNumberOfMarkers();
|
|
while (i--) {
|
|
var marker = this.markerCollection.getMarker(i);
|
|
if (marker !== null) {
|
|
marker.stopToOldTimeout();
|
|
marker.stopDirectionPolyline();
|
|
marker.hide();
|
|
marker.hideMarkerPrevPosition();
|
|
marker.hideMarkerTail();
|
|
|
|
var stationCoverage = this.markerCollection.getStationCoverage(marker.packet.station_id);
|
|
if (stationCoverage) {
|
|
stationCoverage.hide();
|
|
}
|
|
}
|
|
this.markerCollection.removeMarker(i);
|
|
}
|
|
}
|
|
if (this.state.openInfoWindow !== null) {
|
|
this.state.openInfoWindow.hide();
|
|
}
|
|
if (this.oms) {
|
|
this.oms.clearMarkers();
|
|
}
|
|
this.markerCollection.resetAllMarkers();
|
|
};
|
|
|
|
/**
|
|
* Open marker info window
|
|
* @param {trackdirect.models.Marker} marker
|
|
* @param {boolean} disableAutoPan
|
|
*/
|
|
trackdirect.models.Map.prototype.openMarkerInfoWindow = function (
|
|
marker,
|
|
disableAutoPan
|
|
) {
|
|
disableAutoPan =
|
|
typeof disableAutoPan !== "undefined" ? disableAutoPan : true;
|
|
if (marker.getMap() !== null) {
|
|
if (
|
|
this.state.openInfoWindow !== null &&
|
|
this.state.openInfoWindow.getMarker().packet.id != marker.packet.id
|
|
) {
|
|
this.state.openInfoWindow.hide();
|
|
}
|
|
|
|
if (
|
|
this.state.openInfoWindow !== null &&
|
|
this.state.openInfoWindow.getMarker().packet.id == marker.packet.id
|
|
) {
|
|
// Just update existing infoWindow
|
|
this.state.openInfoWindow.setMarker(marker);
|
|
} else {
|
|
this.state.openInfoWindow = new trackdirect.models.InfoWindow(
|
|
marker,
|
|
this,
|
|
disableAutoPan
|
|
);
|
|
}
|
|
this._addInfoWindowListeners(this.state.openInfoWindow);
|
|
this.state.openInfoWindow.show();
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Open latest station info window
|
|
* @param {int} stationId
|
|
*/
|
|
trackdirect.models.Map.prototype.openLatestStationInfoWindow = function (
|
|
stationId
|
|
) {
|
|
var latestVisibleMarker =
|
|
this.markerCollection.getStationLatestVisibleMarker(stationId);
|
|
if (latestVisibleMarker !== null) {
|
|
// open marker info-window since this marker replaced a previous one
|
|
this.openMarkerInfoWindow(latestVisibleMarker);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Open polyline info window
|
|
* @param {trackdirect.models.Marker} marker
|
|
* @param {LatLng} position
|
|
*/
|
|
trackdirect.models.Map.prototype.openPolylineInfoWindow = function (
|
|
marker,
|
|
position
|
|
) {
|
|
if (this.state.openInfoWindow !== null) {
|
|
this.state.openInfoWindow.hide();
|
|
}
|
|
this.state.openInfoWindow = new trackdirect.models.InfoWindow(marker, this);
|
|
this._addInfoWindowListeners(this.state.openInfoWindow);
|
|
this.state.openInfoWindow.show(true, position);
|
|
};
|
|
|
|
/**
|
|
* Add some trackdirect.models.InfoWindow listeners
|
|
* @param {trackdirect.models.InfoWindow} infoWindow
|
|
*/
|
|
trackdirect.models.Map.prototype._addInfoWindowListeners = function (
|
|
infoWindow
|
|
) {
|
|
var me = this;
|
|
infoWindow.addTdListener("station-tail-needed", function (stationId) {
|
|
me._emitTdEventListeners("station-tail-needed", stationId);
|
|
});
|
|
};
|
|
|
|
/**
|
|
* Add listener to events
|
|
* @param {string} event
|
|
* @param {string} handler
|
|
*/
|
|
(trackdirect.models.Map.prototype.addTdListener = function (event, handler) {
|
|
if (!(event in this._tdEventListeners)) {
|
|
this._tdEventListeners[event] = [];
|
|
}
|
|
this._tdEventListeners[event].push(handler);
|
|
}),
|
|
/**
|
|
* Emit all event listeners for a specified event
|
|
* @param {string} event
|
|
* @param {object} arg
|
|
*/
|
|
(trackdirect.models.Map.prototype._emitTdEventListeners = function (
|
|
event,
|
|
arg
|
|
) {
|
|
if (event in this._tdEventListeners) {
|
|
for (var i = 0; i < this._tdEventListeners[event].length; i++) {
|
|
this._tdEventListeners[event][i](arg);
|
|
}
|
|
}
|
|
});
|
|
|
|
/**
|
|
* Make sure all listener that are waiting for a map change event gets called
|
|
*/
|
|
(trackdirect.models.Map.prototype._triggerMapChangeEvent = function () {
|
|
// Execute event "change", but wait some to avoid to many events
|
|
if (this._tdEventTimeout != null) {
|
|
clearTimeout(this._tdEventTimeout);
|
|
}
|
|
var me = this;
|
|
this._tdEventTimeout = window.setTimeout(function () {
|
|
me._emitTdEventListeners("change");
|
|
me._tdEventTimeout = null;
|
|
}, 5);
|
|
}),
|
|
/**
|
|
* Deactivate heatmap
|
|
*/
|
|
(trackdirect.models.Map.prototype._deactivateHeatMap = function () {
|
|
if (typeof google === "object" && typeof google.maps === "object") {
|
|
if (
|
|
typeof this.overlayMapTypes !== "undefined" &&
|
|
this.overlayMapTypes.length > 0
|
|
) {
|
|
this.overlayMapTypes.clear();
|
|
}
|
|
} else if (typeof L === "object") {
|
|
if (this._heatMap !== null) {
|
|
this.removeLayer(this._heatMap);
|
|
}
|
|
}
|
|
});
|
|
|
|
/**
|
|
* Activate heatmap
|
|
*/
|
|
trackdirect.models.Map.prototype._activateHeatMap = function () {
|
|
if (typeof google === "object" && typeof google.maps === "object") {
|
|
if (
|
|
typeof this.overlayMapTypes !== "undefined" &&
|
|
this.overlayMapTypes.length == 0
|
|
) {
|
|
this.overlayMapTypes.setAt(0, this._heatMap);
|
|
}
|
|
} else if (typeof L === "object") {
|
|
if (this._heatMap !== null) {
|
|
this._heatMap.addTo(this);
|
|
this._heatMap.bringToFront();
|
|
this._heatMap.setZIndex(1000);
|
|
}
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Update google map tile layer
|
|
*/
|
|
trackdirect.models.Map.prototype._updateGoogleMapTileLayer = function () {
|
|
this.setMapTypeId(this._supportedMapTypes[this._mapType]);
|
|
};
|
|
|
|
/**
|
|
* Update Leaflet Map Tile Layer
|
|
*/
|
|
trackdirect.models.Map.prototype._updateLeafletTileLayer = function () {
|
|
// Skip this part if we are running the Windy API or if embedded
|
|
if (typeof windyInit !== "function") {
|
|
if (this._leafletTileLayer !== null) {
|
|
this._leafletTileLayer.remove();
|
|
}
|
|
|
|
if (typeof L.mapboxGL === "function") {
|
|
var attribution = "";
|
|
var accessToken = "no-token";
|
|
var style = "";
|
|
|
|
if ("mapboxGLStyle" in this._tdMapOptions) {
|
|
style = this._tdMapOptions["mapboxGLStyle"];
|
|
}
|
|
if ("mapboxGLAccessToken" in this._tdMapOptions) {
|
|
accessToken = this._tdMapOptions["mapboxGLAccessToken"];
|
|
}
|
|
if ("mapboxGLAttribution" in this._tdMapOptions) {
|
|
attribution = this._tdMapOptions["mapboxGLAttribution"];
|
|
}
|
|
|
|
this._leafletTileLayer = L.mapboxGL({
|
|
accessToken: accessToken,
|
|
style: style,
|
|
});
|
|
this.addLayer(this._leafletTileLayer);
|
|
this.attributionControl.addAttribution(attribution);
|
|
} else {
|
|
var options = {};
|
|
if (isHighDensity()) {
|
|
options["ppi"] = "320";
|
|
options["size"] = "512";
|
|
} else if (trackdirect.isMobile) {
|
|
options["ppi"] = "250";
|
|
}
|
|
|
|
this._leafletTileLayer = L.tileLayer.provider(
|
|
this._supportedMapTypes[this._mapType],
|
|
options
|
|
);
|
|
this.addLayer(this._leafletTileLayer);
|
|
this._leafletTileLayer.bringToBack();
|
|
}
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Handle map change event, show markers in new map sectors and hide markers in previous map sectors
|
|
*/
|
|
trackdirect.models.Map.prototype._updateMapContent = function () {
|
|
if (this.getBounds() != null) {
|
|
var previousVisibleMapSectors = [];
|
|
for (var i = 0; i < this._visibleMapSectors.length; i++) {
|
|
previousVisibleMapSectors.push(this._visibleMapSectors[i]);
|
|
}
|
|
|
|
this._visibleMapSectors =
|
|
trackdirect.services.MapSectorCalculator.getMapSectors(this.getBounds());
|
|
this._triggerMapChangeEvent();
|
|
if (!this.state.isFilterMode) {
|
|
if (this.getZoom() < trackdirect.settings.minZoomForMarkers) {
|
|
// When all markers should be hidden we also make sure that markers in current visible map-sectors are removed
|
|
this.hideAllMarkers();
|
|
this._activateHeatMap();
|
|
} else {
|
|
this._deactivateHeatMap();
|
|
|
|
this._hideMarkersInPreviousVisibleMapSectors(previousVisibleMapSectors);
|
|
this._showMarkersInNewVisibleMapSectors(previousVisibleMapSectors);
|
|
if (this._isAnyMarkerDetailsVisible()) {
|
|
this._showVisibleMarkerDetails();
|
|
}
|
|
if (this._isAnyMarkerDetailsHidden()) {
|
|
this._hideVisibleMarkerDetails();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
this._currentContentZoom = this.getZoom();
|
|
};
|
|
|
|
/**
|
|
* Returns true if any marker details should be visible
|
|
* @return {boolean}
|
|
*/
|
|
trackdirect.models.Map.prototype._isAnyMarkerDetailsVisible = function () {
|
|
// This is only needed when zooming (when moving the regular show-marker will also show the details)
|
|
var showPrevPosition =
|
|
this.getZoom() >= trackdirect.settings.minZoomForMarkerPrevPosition &&
|
|
this._currentContentZoom <
|
|
trackdirect.settings.minZoomForMarkerPrevPosition;
|
|
var showMarkerTail =
|
|
this.getZoom() >= trackdirect.settings.minZoomForMarkerTail &&
|
|
this._currentContentZoom < trackdirect.settings.minZoomForMarkerTail;
|
|
var showMarkerLabel =
|
|
this.getZoom() >= trackdirect.settings.minZoomForMarkerLabel &&
|
|
this._currentContentZoom < trackdirect.settings.minZoomForMarkerLabel;
|
|
|
|
if (showPrevPosition || showMarkerTail || showMarkerLabel) {
|
|
return true;
|
|
}
|
|
return false;
|
|
};
|
|
|
|
/**
|
|
* Returns true if any marker details should be hidden
|
|
* @return {boolean}
|
|
*/
|
|
trackdirect.models.Map.prototype._isAnyMarkerDetailsHidden = function () {
|
|
// This is only needed when zooming (when moving the regular show-marker will also show the details)
|
|
var hidePrevPosition =
|
|
this.getZoom() < trackdirect.settings.minZoomForMarkerPrevPosition &&
|
|
this._currentContentZoom >=
|
|
trackdirect.settings.minZoomForMarkerPrevPosition;
|
|
var hideMarkerTail =
|
|
this.getZoom() < trackdirect.settings.minZoomForMarkerTail &&
|
|
this._currentContentZoom >= trackdirect.settings.minZoomForMarkerTail;
|
|
var hideMarkerLabel =
|
|
this.getZoom() < trackdirect.settings.minZoomForMarkerLabel &&
|
|
this._currentContentZoom >= trackdirect.settings.minZoomForMarkerLabel;
|
|
|
|
if (hidePrevPosition || hideMarkerTail || hideMarkerLabel) {
|
|
return true;
|
|
}
|
|
return false;
|
|
};
|
|
|
|
/**
|
|
* Show markers details that should be visible in visible map sectors
|
|
*/
|
|
trackdirect.models.Map.prototype._showVisibleMarkerDetails = function () {
|
|
for (var i = 0; i < this._visibleMapSectors.length; i++) {
|
|
var mapSector = this._visibleMapSectors[i];
|
|
var mapSectorMarkerKeys =
|
|
this.markerCollection.getMapSectorMarkerKeys(mapSector);
|
|
// Array with markers fo this sector exists, we have something to show
|
|
for (var j = 0; j < mapSectorMarkerKeys.length; j++) {
|
|
var markerIdKey = mapSectorMarkerKeys[j];
|
|
var marker = this.markerCollection.getMarker(markerIdKey);
|
|
if (marker === null) {
|
|
continue;
|
|
}
|
|
trackdirect.services.callbackExecutor.addWithPriority(
|
|
marker,
|
|
marker.showMarkerDetails,
|
|
[]
|
|
);
|
|
}
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Hide markers details that should not be visible in visible map sectors
|
|
*/
|
|
trackdirect.models.Map.prototype._hideVisibleMarkerDetails = function () {
|
|
for (var i = 0; i < this._visibleMapSectors.length; i++) {
|
|
var mapSector = this._visibleMapSectors[i];
|
|
var mapSectorMarkerKeys =
|
|
this.markerCollection.getMapSectorMarkerKeys(mapSector);
|
|
// Array with markers fo this sector exists, we have something to hide
|
|
for (var j = 0; j < mapSectorMarkerKeys.length; j++) {
|
|
var markerIdKey = mapSectorMarkerKeys[j];
|
|
var marker = this.markerCollection.getMarker(markerIdKey);
|
|
if (marker === null) {
|
|
continue;
|
|
}
|
|
trackdirect.services.callbackExecutor.addWithPriority(
|
|
marker,
|
|
marker.hideMarkerDetails,
|
|
[]
|
|
);
|
|
}
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Show all markers that should be visible and hide alla markers that should not be visible
|
|
* This is used to show or hide markers when user activate/deactivate filters
|
|
*/
|
|
trackdirect.models.Map.prototype.showHideMarkers = function () {
|
|
if (this.oms) {
|
|
this.oms.unspiderfy();
|
|
}
|
|
if (this.state.isFilterMode) {
|
|
for (var markerIdKey in this.markerCollection.getAllMarkers()) {
|
|
if (this.markerCollection.isExistingMarker(markerIdKey)) {
|
|
var marker = this.markerCollection.getMarker(markerIdKey);
|
|
|
|
if (marker) {
|
|
if (marker.shouldMarkerBeVisible()) {
|
|
marker.showCompleteMarker();
|
|
} else {
|
|
marker.hideCompleteMarker();
|
|
}
|
|
}
|
|
if (marker.packet) {
|
|
this.showTopLabelOnPosition(
|
|
marker.packet.latitude,
|
|
marker.packet.longitude
|
|
);
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
for (var i = 0; i < this._visibleMapSectors.length; i++) {
|
|
var mapSector = this._visibleMapSectors[i];
|
|
var mapSectorMarkerKeys =
|
|
this.markerCollection.getMapSectorMarkerKeys(mapSector);
|
|
|
|
// Array with markers for this sector exists, we have something to show/hide
|
|
for (var j = 0; j < mapSectorMarkerKeys.length; j++) {
|
|
var markerIdKey = mapSectorMarkerKeys[j];
|
|
|
|
if (this.markerCollection.isExistingMarker(markerIdKey)) {
|
|
var marker = this.markerCollection.getMarker(markerIdKey);
|
|
if (marker.shouldMarkerBeVisible()) {
|
|
marker.showCompleteMarker();
|
|
} else {
|
|
marker.hideCompleteMarker();
|
|
}
|
|
this.showTopLabelOnPosition(
|
|
marker.packet.latitude,
|
|
marker.packet.longitude
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Show or hide ALL PHG Circles
|
|
* This is used to show or hide circles when user activate/deactivate PHG circles
|
|
*/
|
|
trackdirect.models.Map.prototype.showHidePHGCircles = function () {
|
|
if (this.getZoom() >= trackdirect.settings.minZoomForMarkers) {
|
|
if (this.state.isFilterMode) {
|
|
for (var markerIdKey in this.markerCollection.getAllMarkers()) {
|
|
if (this.markerCollection.isExistingMarker(markerIdKey)) {
|
|
var marker = this.markerCollection.getMarker(markerIdKey);
|
|
|
|
if (
|
|
marker.showAsMarker &&
|
|
marker.packet.phg != null &&
|
|
marker.getMap() !== null &&
|
|
marker.shouldMarkerBeVisible()
|
|
) {
|
|
if (this.state.showPHGCircles == 0) {
|
|
marker.hidePHGCircle();
|
|
} else if (this.state.showPHGCircles == 1) {
|
|
marker.showPHGCircle(true);
|
|
} else if (this.state.showPHGCircles == 2) {
|
|
marker.showPHGCircle(false);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
for (var i = 0; i < this._visibleMapSectors.length; i++) {
|
|
var mapSector = this._visibleMapSectors[i];
|
|
var mapSectorMarkerKeys =
|
|
this.markerCollection.getMapSectorMarkerKeys(mapSector);
|
|
// Array with markers for this sector exists, we have something to show/hide
|
|
for (var j = 0; j < mapSectorMarkerKeys.length; j++) {
|
|
var markerIdKey = mapSectorMarkerKeys[j];
|
|
|
|
if (this.markerCollection.isExistingMarker(markerIdKey)) {
|
|
var marker = this.markerCollection.getMarker(markerIdKey);
|
|
|
|
if (
|
|
marker.showAsMarker &&
|
|
marker.packet.phg != null &&
|
|
marker.getMap() !== null &&
|
|
marker.shouldMarkerBeVisible()
|
|
) {
|
|
if (this.state.showPHGCircles == 0) {
|
|
marker.hidePHGCircle();
|
|
} else if (this.state.showPHGCircles == 1) {
|
|
marker.showPHGCircle(true);
|
|
} else if (this.state.showPHGCircles == 2) {
|
|
marker.showPHGCircle(false);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Show or hide ALL RNG Circles
|
|
* This is used to show or hide circles when user activate/deactivate PHG circles
|
|
*/
|
|
trackdirect.models.Map.prototype.showHideRNGCircles = function () {
|
|
if (this.getZoom() >= trackdirect.settings.minZoomForMarkers) {
|
|
if (this.state.isFilterMode) {
|
|
for (var markerIdKey in this.markerCollection.getAllMarkers()) {
|
|
if (this.markerCollection.isExistingMarker(markerIdKey)) {
|
|
var marker = this.markerCollection.getMarker(markerIdKey);
|
|
if (
|
|
marker.showAsMarker &&
|
|
marker.packet.rng != null &&
|
|
marker.getMap() !== null &&
|
|
marker.shouldMarkerBeVisible()
|
|
) {
|
|
if (this.state.showRNGCircles == 0) {
|
|
marker.hideRNGCircle();
|
|
} else if (this.state.showRNGCircles == 1) {
|
|
marker.showRNGCircle(true);
|
|
} else if (this.state.showRNGCircles == 2) {
|
|
marker.showRNGCircle(false);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
for (var i = 0; i < this._visibleMapSectors.length; i++) {
|
|
var mapSector = this._visibleMapSectors[i];
|
|
var mapSectorMarkerKeys =
|
|
this.markerCollection.getMapSectorMarkerKeys(mapSector);
|
|
// Array with markers for this sector exists, we have something to show/hide
|
|
for (var j = 0; j < mapSectorMarkerKeys.length; j++) {
|
|
var markerIdKey = mapSectorMarkerKeys[j];
|
|
|
|
if (this.markerCollection.isExistingMarker(markerIdKey)) {
|
|
var marker = this.markerCollection.getMarker(markerIdKey);
|
|
if (
|
|
marker.showAsMarker &&
|
|
marker.packet.rng != null &&
|
|
marker.getMap() !== null &&
|
|
marker.shouldMarkerBeVisible()
|
|
) {
|
|
if (this.state.showRNGCircles == 0) {
|
|
marker.hideRNGCircle();
|
|
} else if (this.state.showRNGCircles == 1) {
|
|
marker.showRNGCircle(true);
|
|
} else if (this.state.showRNGCircles == 2) {
|
|
marker.showRNGCircle(false);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Make sure that all markers that we know is hidden
|
|
*/
|
|
trackdirect.models.Map.prototype.hideAllMarkers = function () {
|
|
for (var markerIdKey in this.markerCollection.getAllMarkers()) {
|
|
var marker = this.markerCollection.getMarker(markerIdKey);
|
|
if (marker !== null) {
|
|
// hide this marker
|
|
marker.hideCompleteMarker();
|
|
}
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Make the label of the latest received marker show on specified position
|
|
* @param {number} latitude
|
|
* @param {number} longitude
|
|
*/
|
|
trackdirect.models.Map.prototype.showTopLabelOnPosition = function (
|
|
latitude,
|
|
longitude
|
|
) {
|
|
var topMarkerIdKey = -1;
|
|
var topMarkerZindex = 0;
|
|
|
|
if (
|
|
Object.keys(
|
|
this.markerCollection.getPositionMarkerIdKeys(latitude, longitude)
|
|
).length > 1
|
|
) {
|
|
for (var markerIdKey in this.markerCollection.getPositionMarkerIdKeys(
|
|
latitude,
|
|
longitude
|
|
)) {
|
|
var marker = this.markerCollection.getMarker(markerIdKey);
|
|
if (marker !== null && marker.shouldMarkerBeVisible()) {
|
|
if (marker.getZIndex() > topMarkerZindex) {
|
|
topMarkerZindex = marker.getZIndex();
|
|
topMarkerIdKey = markerIdKey;
|
|
}
|
|
marker.hideLabel();
|
|
marker.hasLabel = false;
|
|
}
|
|
}
|
|
|
|
if (topMarkerIdKey != -1) {
|
|
var topMarker = this.markerCollection.getMarker(topMarkerIdKey);
|
|
topMarker.hasLabel = true;
|
|
var topMarkerMapSector =
|
|
trackdirect.services.MapSectorCalculator.getMapSector(
|
|
topMarker.getPositionLiteral().lat,
|
|
topMarker.getPositionLiteral().lng
|
|
);
|
|
if (this.state.isFilterMode) {
|
|
topMarker.showLabel();
|
|
} else if (
|
|
this.isMapSectorVisible(topMarkerMapSector) &&
|
|
this.getZoom() >= trackdirect.settings.minZoomForMarkerLabel
|
|
) {
|
|
topMarker.showLabel();
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Hide markers in previously visible map sectors
|
|
* (This should handle both zooming and moving)
|
|
* @param {array} previousVisibleMapSectors
|
|
*/
|
|
trackdirect.models.Map.prototype._hideMarkersInPreviousVisibleMapSectors =
|
|
function (previousVisibleMapSectors) {
|
|
// IMPORTANT: Do this before showing marker since marker may exist in both previus shown sectors and visible sectors
|
|
// (if we show first we may hide something that should be visible)
|
|
|
|
if (this._currentContentZoom >= trackdirect.settings.minZoomForMarkers) {
|
|
var markerIdKeyListToMaybeHide = {};
|
|
var markerIdKeyListNotToHide = {};
|
|
for (var i = 0; i < previousVisibleMapSectors.length; i++) {
|
|
var mapSector = previousVisibleMapSectors[i];
|
|
if (
|
|
!this.isMapSectorVisible(mapSector) ||
|
|
this.getZoom() < trackdirect.settings.minZoomForMarkers
|
|
) {
|
|
// Seems like this sector is not visible any more (or we have zoomed out), hide markers
|
|
var mapSectorMarkerKeys =
|
|
this.markerCollection.getMapSectorMarkerKeys(mapSector);
|
|
for (var j = 0; j < mapSectorMarkerKeys.length; j++) {
|
|
var markerIdKey = mapSectorMarkerKeys[j];
|
|
markerIdKeyListToMaybeHide[markerIdKey] = markerIdKey;
|
|
}
|
|
} else if (this.getZoom() >= trackdirect.settings.minZoomForMarkers) {
|
|
// Seems like this map sector is still visible (and we have not zoomed out)
|
|
var mapSectorMarkerKeys =
|
|
this.markerCollection.getMapSectorMarkerKeys(mapSector);
|
|
for (var j = 0; j < mapSectorMarkerKeys.length; j++) {
|
|
var markerIdKey = mapSectorMarkerKeys[j];
|
|
// Marker exists in map sector that is still visible, do not hide it
|
|
markerIdKeyListNotToHide[markerIdKey] = markerIdKey;
|
|
}
|
|
}
|
|
}
|
|
for (var markerIdKey in markerIdKeyListToMaybeHide) {
|
|
if (markerIdKey in markerIdKeyListNotToHide) {
|
|
continue;
|
|
}
|
|
var marker = this.markerCollection.getMarker(markerIdKey);
|
|
if (marker !== null) {
|
|
// hide this marker
|
|
trackdirect.services.callbackExecutor.addWithPriority(
|
|
marker,
|
|
marker.hideCompleteMarker,
|
|
[]
|
|
);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Show markers in new visible map sectors
|
|
* @param {array} previousVisibleMapSectors
|
|
*/
|
|
trackdirect.models.Map.prototype._showMarkersInNewVisibleMapSectors = function (
|
|
previousVisibleMapSectors
|
|
) {
|
|
// Show new markers that is visible in new map sectors
|
|
// This should handle both zooming and moving
|
|
|
|
if (this.getZoom() >= trackdirect.settings.minZoomForMarkers) {
|
|
for (var i = 0; i < this._visibleMapSectors.length; i++) {
|
|
var mapSector = this._visibleMapSectors[i];
|
|
if (
|
|
previousVisibleMapSectors.indexOf(mapSector) == -1 ||
|
|
this._currentContentZoom < trackdirect.settings.minZoomForMarkers
|
|
) {
|
|
// Seems like this sector is new (or we have zoomed in now), show markers
|
|
var mapSectorMarkerKeys =
|
|
this.markerCollection.getMapSectorMarkerKeys(mapSector);
|
|
for (var j = 0; j < mapSectorMarkerKeys.length; j++) {
|
|
var markerIdKey = mapSectorMarkerKeys[j];
|
|
var marker = this.markerCollection.getMarker(markerIdKey);
|
|
if (marker !== null) {
|
|
trackdirect.services.callbackExecutor.addWithPriority(
|
|
marker,
|
|
marker.showCompleteMarker,
|
|
[]
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Also make sure all stations with a visible coverage is shown
|
|
var stationIdList =
|
|
this.markerCollection.getStationIdListWithVisibleCoverage();
|
|
for (var i = 0; i < stationIdList.length; i++) {
|
|
var latestMarker = this.markerCollection.getStationLatestMarker(
|
|
stationIdList[i]
|
|
);
|
|
if (latestMarker !== null) {
|
|
if (latestMarker.shouldMarkerBeVisible() && latestMarker.showAsMarker) {
|
|
latestMarker.show();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Set map initial position
|
|
*/
|
|
trackdirect.models.Map.prototype._setMapInitialLocation = function () {
|
|
var zoom = this._getInitialZoom();
|
|
if (
|
|
typeof this._tdMapOptions.initCenter !== "undefined" &&
|
|
this._tdMapOptions.initCenter !== null
|
|
) {
|
|
var pos = this._tdMapOptions.initCenter;
|
|
this.setCenter(pos, zoom);
|
|
} else {
|
|
this.setMapDefaultLocation();
|
|
this.setZoom(zoom);
|
|
}
|
|
this._emitTdEventListeners("change");
|
|
};
|
|
|
|
/**
|
|
* Set map default location
|
|
*/
|
|
trackdirect.models.Map.prototype.setMapDefaultLocation = function (
|
|
setDefaultZoom
|
|
) {
|
|
setDefaultZoom =
|
|
typeof setDefaultZoom !== "undefined" ? setDefaultZoom : false;
|
|
|
|
var defaultLatitude =
|
|
typeof this._tdMapOptions.defaultLatitude !== "undefined"
|
|
? this._tdMapOptions.defaultLatitude
|
|
: 59.35;
|
|
var defaultLongitude =
|
|
typeof this._tdMapOptions.defaultLongitude !== "undefined"
|
|
? this._tdMapOptions.defaultLongitude
|
|
: 18.05;
|
|
|
|
var pos = {
|
|
lat: parseFloat(defaultLatitude),
|
|
lng: parseFloat(defaultLongitude),
|
|
};
|
|
|
|
if (setDefaultZoom) {
|
|
if (trackdirect.isMobile) {
|
|
this.setCenter(pos, trackdirect.settings.defaultCurrentZoomMobile);
|
|
} else {
|
|
this.setCenter(pos, trackdirect.settings.defaultCurrentZoom);
|
|
}
|
|
} else {
|
|
this.setCenter(pos);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Add marker to multiple Map-Sectors, useful for very long polylines related to a marker
|
|
* @param {int} markerIdKey
|
|
* @param {LatLngLiteral} startLatLng
|
|
* @param {LatLngLiteral} endLatLng
|
|
*/
|
|
trackdirect.models.Map.prototype.addMarkerToMapSectorInterval = function (
|
|
markerIdKey,
|
|
startLatLng,
|
|
endLatLng
|
|
) {
|
|
var minLat = startLatLng.lat;
|
|
var maxLat = endLatLng.lat;
|
|
var minLng = startLatLng.lng;
|
|
var maxLng = endLatLng.lng;
|
|
if (endLatLng.lat < minLat) {
|
|
minLat = endLatLng.lat;
|
|
maxLat = startLatLng.lat;
|
|
}
|
|
if (endLatLng.lng < minLng) {
|
|
minLng = endLatLng.lng;
|
|
maxLng = startLatLng.lng;
|
|
}
|
|
for (var lat = Math.floor(minLat); lat <= Math.ceil(maxLat); lat++) {
|
|
for (var lng = Math.floor(minLng); lng <= Math.ceil(maxLng); lng++) {
|
|
var markerMapSector =
|
|
trackdirect.services.MapSectorCalculator.getMapSector(lat, lng);
|
|
|
|
this.markerCollection.addMarkerToMapSector(markerIdKey, markerMapSector);
|
|
|
|
if (this.isMapSectorVisible(markerMapSector)) {
|
|
if (this._newMarkersToShow.indexOf(markerIdKey) < 0) {
|
|
this._newMarkersToShow.push(markerIdKey);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Add marker the related map sector based in latest packet
|
|
* @param {int} markerIdKey
|
|
* @param {object} packet
|
|
* @param {boolean} tryToShowPacket
|
|
*/
|
|
trackdirect.models.Map.prototype.addMarkerToMapSectors = function (
|
|
markerIdKey,
|
|
packet,
|
|
tryToShowPacket
|
|
) {
|
|
var markerMapSectors = [];
|
|
|
|
markerMapSectors.push(packet.map_sector);
|
|
if (
|
|
typeof packet.related_map_sectors !== "undefined" &&
|
|
packet.related_map_sectors !== null
|
|
) {
|
|
for (var i = 0; i < packet.related_map_sectors.length; i++) {
|
|
markerMapSectors.push(packet.related_map_sectors[i]);
|
|
}
|
|
}
|
|
|
|
for (var i = 0; i < markerMapSectors.length; i++) {
|
|
var markerMapSector = markerMapSectors[i];
|
|
this.markerCollection.addMarkerToMapSector(markerIdKey, markerMapSector);
|
|
|
|
if (tryToShowPacket) {
|
|
if (this.isMapSectorVisible(markerMapSector)) {
|
|
if (this._newMarkersToShow.indexOf(markerIdKey) < 0) {
|
|
this._newMarkersToShow.push(markerIdKey);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Initialize map basic events
|
|
*/
|
|
trackdirect.models.Map.prototype._initMapEvents = function () {
|
|
if (typeof google === "object" && typeof google.maps === "object") {
|
|
this._initGoogleMapEvents();
|
|
} else if (typeof L === "object") {
|
|
this._initLeafletMapEvents();
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Initialize google map basic events
|
|
*/
|
|
trackdirect.models.Map.prototype._initGoogleMapEvents = function () {
|
|
var me = this;
|
|
google.maps.event.addListener(this, "mousemove", function (event) {
|
|
me._renderCordinatesContainer(event.latLng);
|
|
});
|
|
|
|
google.maps.event.addListener(this, "idle", function () {
|
|
me._updateMapContent();
|
|
});
|
|
|
|
google.maps.event.addListener(this, "maptypeid_changed", function () {
|
|
me._updateMapContent();
|
|
});
|
|
|
|
google.maps.event.addListener(this, "bounds_changed", function () {
|
|
if (me.isMapReady()) {
|
|
me._emitTdEventListeners("moving");
|
|
}
|
|
});
|
|
};
|
|
|
|
/**
|
|
* Initialize leaflet map basic events
|
|
*/
|
|
trackdirect.models.Map.prototype._initLeafletMapEvents = function () {
|
|
var me = this;
|
|
this.on("mousemove", function (event) {
|
|
me._renderCordinatesContainer(event.latlng);
|
|
});
|
|
|
|
this.on("moveend", function () {
|
|
me._updateMapContent();
|
|
});
|
|
/*
|
|
this.on('maptypeid_changed', function() {
|
|
me._updateMapContent();
|
|
});
|
|
*/
|
|
this.on("move", function () {
|
|
if (me.isMapReady()) {
|
|
me._emitTdEventListeners("moving");
|
|
}
|
|
});
|
|
};
|
|
|
|
/**
|
|
* Initialize OMS
|
|
*/
|
|
trackdirect.models.Map.prototype._initOms = function () {
|
|
var options = {};
|
|
options["nearbyDistance"] = 12;
|
|
if (typeof google === "object" && typeof google.maps === "object") {
|
|
var mti = google.maps.MapTypeId;
|
|
this.oms = new OverlappingMarkerSpiderfier(this, options);
|
|
this.oms.legColors.usual[mti.HYBRID] = this.oms.legColors.usual[
|
|
mti.SATELLITE
|
|
] = "#fff";
|
|
this.oms.legColors.usual[mti.TERRAIN] = this.oms.legColors.usual[
|
|
mti.ROADMAP
|
|
] = "#222";
|
|
this.oms.legColors.highlighted[mti.HYBRID] = this.oms.legColors.highlighted[
|
|
mti.SATELLITE
|
|
] = "#f00";
|
|
this.oms.legColors.highlighted[mti.TERRAIN] =
|
|
this.oms.legColors.highlighted[mti.ROADMAP] = "#f00";
|
|
} else if (typeof L === "object") {
|
|
this.oms = new OverlappingMarkerSpiderfier(this, options);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Initialize info window for markers
|
|
*/
|
|
trackdirect.models.Map.prototype._initInfoWindowEvent = function () {
|
|
var me = this;
|
|
if (this.oms) {
|
|
this.oms.addListener("click", function (marker, event) {
|
|
me.openMarkerInfoWindow(marker, false);
|
|
});
|
|
} else {
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Get default google "map options", used for initializing google map
|
|
* @return {object}
|
|
*/
|
|
trackdirect.models.Map.prototype._getGoolgeMapOptions = function () {
|
|
var zoom = this._getInitialZoom();
|
|
var mapOptions = {
|
|
zoom: zoom,
|
|
panControl: false,
|
|
zoomControl: true,
|
|
zoomControlOptions: {
|
|
position: google.maps.ControlPosition.RIGHT_BOTTOM,
|
|
},
|
|
mapTypeControl: false,
|
|
scaleControl: false,
|
|
streetViewControl: false,
|
|
overviewMapControl: false,
|
|
fullscreenControl: false,
|
|
mapTypeId: google.maps.MapTypeId.ROADMAP,
|
|
gestureHandling: "greedy",
|
|
};
|
|
|
|
mapOptions.mapTypeId = this._supportedMapTypes[this._mapType];
|
|
return mapOptions;
|
|
};
|
|
|
|
/**
|
|
* Get default leaflet "map options", used for initializing google map
|
|
* @return {object}
|
|
*/
|
|
trackdirect.models.Map.prototype._getLeafletMapOptions = function () {
|
|
var zoom = this._getInitialZoom();
|
|
var mapOptions = {
|
|
zoom: zoom,
|
|
zoomControl: true,
|
|
attributionControl: true,
|
|
zoomControl: false,
|
|
minZoom: 3,
|
|
maxZoom: 16,
|
|
closePopupOnClick: false,
|
|
};
|
|
|
|
return mapOptions;
|
|
};
|
|
|
|
/**
|
|
* Get initial zoom
|
|
* @return {int}
|
|
*/
|
|
trackdirect.models.Map.prototype._getInitialZoom = function () {
|
|
var zoom = trackdirect.settings.defaultCurrentZoom;
|
|
if (
|
|
typeof this._tdMapOptions.zoom !== "undefined" &&
|
|
this._tdMapOptions.zoom !== null
|
|
) {
|
|
zoom = parseInt(this._tdMapOptions.zoom);
|
|
} else if (trackdirect.isMobile) {
|
|
zoom = trackdirect.settings.defaultCurrentZoomMobile;
|
|
}
|
|
|
|
return zoom;
|
|
};
|
|
|
|
/**
|
|
* Get radius in Km (radius is from center of current map view to the most north east position)
|
|
* @return {int}
|
|
*/
|
|
trackdirect.models.Map.prototype.getCurrentRadiusInKm = function () {
|
|
if (this.getBounds() != null) {
|
|
if (typeof google === "object" && typeof google.maps === "object") {
|
|
var latLng = this.getBounds().getNorthEast();
|
|
var latLngLiteral = { lat: latLng.lat(), lng: latLng.lng() };
|
|
} else if (typeof L === "object") {
|
|
var latLng = this.getBounds().getNorthEast();
|
|
var latLngLiteral = { lat: latLng.lat, lng: latLng.lng };
|
|
}
|
|
return (
|
|
trackdirect.services.distanceCalculator.getDistance(
|
|
this.getCenterLiteral(),
|
|
latLngLiteral
|
|
) / 1000
|
|
);
|
|
}
|
|
return 0;
|
|
};
|
|
|
|
/**
|
|
* Print position in the cordinates container
|
|
* @return {google.maps.LatLng/L.LatLng/LatLngLiteral} mouseLatLng
|
|
*/
|
|
trackdirect.models.Map.prototype._renderCordinatesContainer = function (
|
|
mouseLatLng
|
|
) {
|
|
var options = this.getTdMapOptions();
|
|
if (typeof options.cordinatesContainer === "undefined") {
|
|
return;
|
|
}
|
|
if (options.cordinatesContainer == null) {
|
|
return;
|
|
}
|
|
|
|
var lat = null;
|
|
var lng = null;
|
|
if (typeof mouseLatLng.lat == "function") {
|
|
lat = mouseLatLng.lat();
|
|
lng = mouseLatLng.lng();
|
|
} else {
|
|
lat = mouseLatLng.lat;
|
|
lng = mouseLatLng.lng;
|
|
}
|
|
|
|
if (lat <= 90 && lat >= -90 && lng <= 180 && lng >= -180) {
|
|
var content = "";
|
|
content += this._getGpsDegreeFromGpsDecimal(lat.toFixed(5), "lat");
|
|
content += " " + this._getGpsDegreeFromGpsDecimal(lng.toFixed(5), "lon");
|
|
content += "<br>" + lat.toFixed(5) + ", " + lng.toFixed(5);
|
|
content += "<br>" + this._getMaidenheadLocatorFromGpsDecimal(lat, lng);
|
|
|
|
$("#" + options.cordinatesContainer).html(content);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Convert decimal gps position to degree format
|
|
* @param {float} dms
|
|
* @param {string} type
|
|
* @return {string}
|
|
*/
|
|
trackdirect.models.Map.prototype._getGpsDegreeFromGpsDecimal = function (
|
|
dms,
|
|
type
|
|
) {
|
|
var sign = 1,
|
|
Abs = 0;
|
|
var days, minutes, secounds, direction;
|
|
|
|
if (dms < 0) {
|
|
sign = -1;
|
|
}
|
|
Abs = Math.abs(Math.round(dms * 1000000));
|
|
//Math.round is used to eliminate the small error caused by rounding in the computer:
|
|
//e.g. 0.2 is not the same as 0.20000000000284
|
|
//Error checks
|
|
if (type == "lat" && Abs > 90 * 1000000) {
|
|
//alert(" Degrees Latitude must be in the range of -90. to 90. ");
|
|
return false;
|
|
} else if (type == "lon" && Abs > 180 * 1000000) {
|
|
//alert(" Degrees Longitude must be in the range of -180 to 180. ");
|
|
return false;
|
|
}
|
|
|
|
days = Math.floor(Abs / 1000000);
|
|
minutes = Math.floor((Abs / 1000000 - days) * 60);
|
|
secounds = (
|
|
(Math.floor(((Abs / 1000000 - days) * 60 - minutes) * 100000) * 60) /
|
|
100000
|
|
).toFixed();
|
|
days = days * sign;
|
|
if (type == "lat") direction = days < 0 ? "S" : "N";
|
|
if (type == "lon") direction = days < 0 ? "W" : "E";
|
|
//else return value
|
|
return days * sign + "º " + minutes + "' " + secounds + "'' " + direction;
|
|
};
|
|
|
|
/**
|
|
* Convert decimal gps position to maidenhead locator
|
|
* @param {float} lat
|
|
* @param {float} lng
|
|
* @return {string}
|
|
*/
|
|
trackdirect.models.Map.prototype._getMaidenheadLocatorFromGpsDecimal = function (
|
|
lat,
|
|
lng,
|
|
) {
|
|
const chars = 'ABCDEFGHIJKLMNOPQRSTUVX';
|
|
var result = '';
|
|
lng = lng + 180;
|
|
lat = lat + 90;
|
|
result = chars.charAt(parseInt(lng / 20));
|
|
result += chars.charAt(parseInt(lat / 10));
|
|
result += parseInt(lng / 2 % 10);
|
|
result += parseInt(lat % 10);
|
|
lng_r = (lng - parseInt(lng/2)*2) * 60;
|
|
lat_r = (lat - parseInt(lat)) * 60;
|
|
result += chars.charAt(parseInt(lng_r/5));
|
|
result += chars.charAt(parseInt(lat_r/2.5));
|
|
return result;
|
|
};
|