diff --git a/ipmd/static/ipmd/js/ipmdlib.js b/ipmd/static/ipmd/js/ipmdlib.js index cab3b064937d27a55ba9693d28158d60577a02c9..f51a2bd3746fd548eec04f4e9168e1a6d25f7819 100644 --- a/ipmd/static/ipmd/js/ipmdlib.js +++ b/ipmd/static/ipmd/js/ipmdlib.js @@ -380,8 +380,10 @@ var maps = {}; * Requires OpenLayers v. 4 * @param {String} containerId * @param {JSON} geoJson + * @param {Array} countryCodeList + * @param {Function} featureClickedCallback Callback function taking parameters ({String} id, {Array<Float>} coordinate) */ -async function initDataSourceMap(containerId, geoJson, countryCodeList) +async function initDataSourceMap(containerId, geoJson, countryCodeList, featureClickedCallback) { let map = maps[containerId]; @@ -470,6 +472,70 @@ async function initDataSourceMap(containerId, geoJson, countryCodeList) extent = featureOverlay.getSource().getExtent(); map.getView().fit(extent, map.getSize()); } + + map.on('singleclick', function(evt) { + var pixel = map.getEventPixel(evt.originalEvent); + var coordinate = map.getEventCoordinate(evt.originalEvent); + displayFeatureDetails(map, pixel, coordinate, featureClickedCallback); + }); +} + + +/** + * When a user clicks on the map, handles whatever was clicked (station, point in area, point outside any feature/area) + * @param {ol.map} map + * @param {ol.Pixel} pixel + * @param {ol.coordinate} coordinate + * @param {Function} featureClickedCallback Callback function taking parameters ({String} id, {Array<Float>} coordinate) + */ +function displayFeatureDetails(map, pixel, coordinate, featureClickedCallback) { + var features = []; + map.forEachFeatureAtPixel(pixel, function(feature,layer){ + features.push(feature); + }); + + if (features.length == 1) { + // A station? Select station using features[i].getId() in callback + if(features[0].getId() !== undefined) + { + console.info("Station clicked: " + features[0].get("name") + ",id=" + features[0].getId()); + featureClickedCallback(features[0].getId(), getDecimalDegrees(map, coordinate)); + } + // An area? Return the coordinate of clicked point in callback + else + { + featureClickedCallback(null, getDecimalDegrees(map, coordinate)); + console.info("Area clicked"); + } + } + // Display popup,so that user can select their station + else if(features.length > 1) + { + console.info("Multiple stations clicked. TODO: Let user select from a popup") + for(var i in features) + { + // A station? Select station using features[i].getId() in callback + if(features[i].getId() !== undefined) + { + console.info("Station clicked: " + features[i].get("name") + ",id=" + features[i].getId()); + } + } + } + else + { + // No feature clicked. Do anything? + } +}; + +/** + * + * @param {ol.Map} map + * @param {Array<Float>} coordinate + * @returns the pixel coordinate from a map converted to WGS84 Decimal degrees + */ +function getDecimalDegrees(map, coordinate) +{ + return ol.coordinate.toStringXY(ol.proj.transform(coordinate, map.getView().getProjection().getCode(), 'EPSG:4326'),5); } async function getCountryBoundaries(countryCodeList) diff --git a/ipmd/templates/ipmd/saddlegallmidgeform.html b/ipmd/templates/ipmd/saddlegallmidgeform.html index 26e2ba86282e94aa0099e7683cc18ab12c780e28..c22bb02dac9924ac0aec75cda37edc43512c0cd9 100644 --- a/ipmd/templates/ipmd/saddlegallmidgeform.html +++ b/ipmd/templates/ipmd/saddlegallmidgeform.html @@ -178,7 +178,12 @@ } // Display map - initDataSourceMap("historicDatasourceMap", JSON.parse(currentWeatherDatasource.spatial.geoJSON), currentWeatherDatasource.spatial.countries); + initDataSourceMap( + "historicDatasourceMap", + JSON.parse(currentWeatherDatasource.spatial.geoJSON), + currentWeatherDatasource.spatial.countries, + handleHistoricDatasourceMapClicked + ); let sourceInfo = document.getElementById("historicSourceInfo"); sourceInfo.innerHTML = currentWeatherDatasource.description; @@ -200,6 +205,36 @@ //console.info(currentWeatherDatasource); } + function handleHistoricDatasourceMapClicked(id, coordinate) + { + + console.info("Map clicked, station=" + id +", coordinate=" + coordinate + ". TODO: select station and/or populate lat/lon fields"); + // id != null => station. Pull station coordinates from source list to avoid inacurracies in user's map click coordinate + if(id !== null) + { + // Set the selected station + setSelection(selectList, id); + handleWeatherStationSelected(selectList); + // Call handleWeatherStationSelected() + } + // id == null => area. Use the provided coordinate + } + + function setSelection(selectList, optionValue) + { + for(let i=0;i<selectList.options.length; i++) + { + if(selectList.options[i].value == optionValue) + { + selectList.options[i].selected = true; + } + else + { + selectList.options[i].selected = false; + } + } + } + function handleForecastSourceSelected(forecastSourceSelectList) { currentForecastWeatherDatasource = getWeatherDatasource(