diff --git a/ipmd/static/ipmd/js/ipmdlib.js b/ipmd/static/ipmd/js/ipmdlib.js index 30859cd26e81f087ec1346d9a988b476b5e63c4c..e17d43259cf2b1f9308b54c4d76fa9fad21c177b 100644 --- a/ipmd/static/ipmd/js/ipmdlib.js +++ b/ipmd/static/ipmd/js/ipmdlib.js @@ -578,7 +578,8 @@ function destroyDataSourceMap(containerId) * @param {String} containerId * @param {JSON} geoJson * @param {Array} countryCodeList - * @param {Function} featureClickedCallback Callback function taking parameters ({String} id, {Array<Float>} coordinate) + * @param {Boolean} clickable if null or false; clicking does nothing + * @param {Function} featureClickedCallback Callback function taking parameters ({String} id, {Array<Float>} coordinate). If null => do nothing when user clicks in map */ async function initDataSourceMap(containerId, geoJson, countryCodeList, featureClickedCallback) { @@ -592,7 +593,7 @@ async function initDataSourceMap(containerId, geoJson, countryCodeList, featureC } // If no data, no map - if((isEmpty(geoJson) || isEmpty(geoJson.features) || geoJson.features.length == 0) && (countryCodeList == null || countryCodeList.length == 0)) + if((isEmpty(geoJson) || ((isEmpty(geoJson.features) || geoJson.features.length == 0) && ! (geoJson.type != undefined && geoJson.type.toLowerCase() == "sphere")) ) && (countryCodeList == null || countryCodeList.length == 0)) { document.getElementById(containerId).innerHTML = "NO GEODATA PROVIDED BY WEATHER DATA SOURCE"; return; @@ -627,9 +628,10 @@ async function initDataSourceMap(containerId, geoJson, countryCodeList, featureC map.setView(view); // Read the datasource's geoJson features - let features = new ol.Collection(); + let drawnFeatures = undefined; + let features = new ol.Collection(); let format = new ol.format.GeoJSON(); - let drawnFeatures = await format.readFeatures( + drawnFeatures = await format.readFeatures( await getDatasourceFeatures(geoJson, countryCodeList), { dataProjection: 'EPSG:4326', @@ -639,55 +641,66 @@ async function initDataSourceMap(containerId, geoJson, countryCodeList, featureC // Add any features to the featureOverlay let featureOverlay = undefined; - if(drawnFeatures != undefined) - { - // Create an empty layer - featureOverlay = new ol.layer.Vector({ - source: new ol.source.Vector({ - features: features - }), - style: styleUnselected - }); - // Add the stations or area + + // Create an empty layer + featureOverlay = new ol.layer.Vector({ + source: new ol.source.Vector({ + features: features + }), + style: styleUnselected + }); + // Add the stations or area + if(drawnFeatures != undefined && drawnFeatures.length > 0) + { featureOverlay.getSource().addFeatures(drawnFeatures); - featureOverlay.setMap(map); - // Fit the features to the extent of the map - extent = featureOverlay.getSource().getExtent(); + let extent = featureOverlay.getSource().getExtent(); map.getView().fit(extent, map.getSize()); } + // If no stations / area: show the world + else + { + map.getView().setZoom(1); + map.getView().setCenter(ol.proj.transform([0.0,15.0], 'EPSG:4326', map.getView().getProjection().getCode())); + + } + featureOverlay.setMap(map); + + + if(featureClickedCallback != undefined && featureClickedCallback != null) + { + /* + * A little bit of this and that to make feature selection work the way we want + * - Highlight a selected station (but only one station, multiple select is not allowed) + * - If user clicks on multiple stations, zoom in to make it easy to pick the right one + */ - /* - * A little bit of this and that to make feature selection work the way we want - * - Highlight a selected station (but only one station, multiple select is not allowed) - * - If user clicks on multiple stations, zoom in to make it easy to pick the right one - */ - - let selectInteraction = new ol.interaction.Select({ - toggleCondition: ol.events.condition.never // Only one can be selected at a time - }); - map.addInteraction(selectInteraction); - selectInteraction.on("select", function(e){ - // If it's an area (id == undefined), don't mark it as selected - if(e.target.getFeatures().getLength() > 0 && e.target.getFeatures().item(0).getId() == undefined) - { - e.target.getFeatures().clear(); - } - else if(e.target.getFeatures().getLength() == 1) - { - let feature = e.target.getFeatures().item(0); - featureClickedCallback(feature.getId(), undefined); - } - }); - - // We add this in order to detect if multiple features were clicked on, since the selectInteraction - // does not catch that - map.on('singleclick', function(evt) { - var pixel = map.getEventPixel(evt.originalEvent); - var coordinate = map.getEventCoordinate(evt.originalEvent); - handleMapClicked(map, featureOverlay, pixel, coordinate, featureClickedCallback); - }); + let selectInteraction = new ol.interaction.Select({ + toggleCondition: ol.events.condition.never // Only one can be selected at a time + }); + map.addInteraction(selectInteraction); + selectInteraction.on("select", function(e){ + // If it's an area (id == undefined), don't mark it as selected + if(e.target.getFeatures().getLength() > 0 && e.target.getFeatures().item(0).getId() == undefined) + { + e.target.getFeatures().clear(); + } + else if(e.target.getFeatures().getLength() == 1) + { + let feature = e.target.getFeatures().item(0); + featureClickedCallback(feature.getId(), undefined); + } + }); + + // We add this in order to detect if multiple features were clicked on, since the selectInteraction + // does not catch that + map.on('singleclick', function(evt) { + var pixel = map.getEventPixel(evt.originalEvent); + var coordinate = map.getEventCoordinate(evt.originalEvent); + handleMapClicked(map, featureOverlay, pixel, coordinate, featureClickedCallback); + }); + } } /** @@ -699,8 +712,12 @@ async function initDataSourceMap(containerId, geoJson, countryCodeList, featureC */ async function getDatasourceFeatures(geoJson, countryCodeList) { + if(geoJson != null && geoJson.type != undefined && geoJson.type.toLowerCase() == "sphere") + { + return {"type": "FeatureCollection","features": []}; + } // If we have geoJson available, we display that - if (geoJson != null && geoJson.features !== undefined && geoJson.features.length > 0) { + if (geoJson != null && geoJson.features !== undefined && geoJson.features.length > 0) { return geoJson; } return await getCountryBoundaries(countryCodeList); @@ -747,9 +764,9 @@ function handleMapClicked(map, layer, pixel, coordinate, featureClickedCallback) features.push(feature); }); - if (features.length == 1) { - // Area - if(features[0].getId() === undefined) + if (features.length == 1 || layer.getSource().getFeatures().length == 0) { + // Area / sphere (whole globe) + if(layer.getSource().getFeatures().length == 0 || features[0].getId() === undefined) { // We must place a marker where the user clicked let marker = map.getOverlayById("marker"); @@ -787,7 +804,7 @@ function handleMapClicked(map, layer, pixel, coordinate, featureClickedCallback) { map.getView().setCenter(coordinate); map.getView().setZoom(map.getView().getZoom() + 2); - } + } }; function createMarkerOverlay(coordinate) diff --git a/ipmd/templates/ipmd/saddlegallmidgeform.html b/ipmd/templates/ipmd/saddlegallmidgeform.html index 077d49f25658637338c611ba17fe4c61c0fbe01d..9e23a4304e0707aa762f74dd55bb03d0b9b002a3 100644 --- a/ipmd/templates/ipmd/saddlegallmidgeform.html +++ b/ipmd/templates/ipmd/saddlegallmidgeform.html @@ -300,12 +300,12 @@ let geoJson = JSON.parse(currentForecastWeatherDatasource.spatial.geoJSON); - // Display map + // Display non-interactive map initDataSourceMap( "forecastDatasourceMap", geoJson, currentForecastWeatherDatasource.spatial.countries, - function(){} // We don't do nothing, right? + null // We don't do nothing, right? ); let sourceInfo = document.getElementById("forecastSourceInfo");