diff --git a/gazetteer.js b/gazetteer.js new file mode 100644 index 0000000..8018e01 --- /dev/null +++ b/gazetteer.js @@ -0,0 +1,181 @@ +// Gazetteer/AddressBase Form Code + +let zoomToFn; + +// Initilaise the Gazetteer form +function initGazetteer(zoomTo) { + // Store the zoom function pointer here for use when a result is clicked + zoomToFn = zoomTo + + // Add a listener to the Gazetteer search form + const form = document.getElementById("gazetteer_search"); + form.addEventListener("submit", (evt) => submitGazetteerForm(evt)); + + // Add a listener to the Gazetteer results list + const selector = document.getElementById("gazetteer_result"); + selector.addEventListener("change", (evt) => selectGazetteerResult(evt)); + + // Add a listener to the AddressBase search form + const form2 = document.getElementById("addressbase_search"); + form2.addEventListener("submit", (evt) => submitAddressBaseForm(evt)); + + // Add a listener to the AddressBase results list + const selector2 = document.getElementById("addressbase_result"); + selector2.addEventListener("change", (evt) => selectAddressBaseResult(evt)); +} + +// Call the Gazetteer API when a search is requested +function submitGazetteerForm(evt) +{ + // Stop the form refreshing the page + evt.preventDefault(); + + // Call the Gazetteer API + callGazetteerApi(evt.target[0].value).then(data => { + // Handle the response + handleGazetteerResponses(data); + }); +} + +// Called when a Gazetteer result is selected +function selectGazetteerResult(evt) +{ + // Zoom the map to the selected result + zoomToFn(evt.target.value); +} + +// Call the AddressBase API when a search is requested +function submitAddressBaseForm(evt) +{ + // Stop the form refreshing the page + evt.preventDefault(); + // Call the AddressBase API + callAddressBaseApi(evt.target[0].value).then(data => { + // Handle the response + handleAddressBaseResponses(data); + }); +} + +// Called when an AddressBase result is selected +function selectAddressBaseResult(evt) +{ + // Zoom the map to the selected result + zoomToFn(evt.target.value); +} + +// API Code + +// Gazetteer API URL +// Sample request: https://api.themapcloud.com/api/v2/gazetteer/search-all/?token= +const gazetteerAPI = "https://api.themapcloud.com/api/v2/gazetteer/search-all/"; + +// AddressBase Postcode API URL +/* Sample request: + https://api.themapcloud.com/address/addressbase/postcode? + token=& + pc=& + addrformat=1& (1,2,3 = one line address, multi-line address, individual fields) + format=json& (json or xml) + datatype=dpa (dpa or lpi = post office vs local govt gazetteer) +*/ +const addressBaseAPI = "https://api.themapcloud.com/address/addressbase/postcode"; + +// Read the token from the .env parameters +const token = import.meta.env.VITE_TMC_TOKEN; + +// Asyncronous call to the Gazetteer API +async function callGazetteerApi(searchFor) { + // construct the url + const url = gazetteerAPI + searchFor + "?token=" + token; + // make the call and await the response + const response = await fetch(url, { + method: "GET", + headers: { + "Accept": "application/json", + } + }); + // On success, convert the result to json + return response.json(); +} + +// Handle the Gazetteer responses +function handleGazetteerResponses(data) { + // Get the select options list + var dataList = document.getElementById("gazetteer_result"); + // Empty previous results + while (dataList.firstChild) { dataList.removeChild(dataList.firstChild);} + // Create and add a default option + var defaultOption = document.createElement('option'); + defaultOption.value = ""; + defaultOption.text = "select to zoom..."; + defaultOption.selected = true; + dataList.appendChild(defaultOption); + + // Disable the select if there were no results + dataList.disabled = data.matches.length < 1; + + // Add the results to the select options + data.matches.forEach(match => { + // Create an option + var option = document.createElement('option'); + // Set the value to the x,y coordinate string + option.value = match.geometry_x + "," + match.geometry_y; + // Set the text to the location text + option.text = match.location; + // Don't select this option yet + option.selected = false; + // Add to the list + dataList.appendChild(option); + }); +} + +// Asyncronous call to the AddressBase API +async function callAddressBaseApi(postcode) { + // construct the url + const url = addressBaseAPI + "?token=" + token + "&pc=" + postcode + "&addrformat=1&format=json&datatype=dpa"; + // make the call and await the response + const response = await fetch(url, { + method: "GET", + headers: { + "Accept": "application/json", + } + }); + // On success, convert the result to json + return response.json(); +} + +// Handle the AddressBase responses +function handleAddressBaseResponses(data) { + // Get the select options list + var dataList = document.getElementById("addressbase_result"); + + // Empty previous results + while (dataList.firstChild) { dataList.removeChild(dataList.firstChild);} + + // Create and add a default option + var defaultOption = document.createElement('option'); + defaultOption.value = ""; + defaultOption.text = "select to zoom..."; + defaultOption.selected = true; + dataList.appendChild(defaultOption); + + // Disable the select if there were no results + dataList.disabled = data.results.length < 1; + + // Add the results to the select options + data.results.forEach(result => { + // Create an option + var option = document.createElement('option'); + // Set the value to the x,y coordinate string + option.value = result.x_coord + "," + result.y_coord; + // Set the text to the address text + option.text = result.address; + // Don't select this option yet + option.selected = false; + // Add to the list + dataList.appendChild(option); + }); +} + +// Export the init function for the main script to pick up +export default initGazetteer diff --git a/index.html b/index.html index afcb4ee..99ab2d9 100644 --- a/index.html +++ b/index.html @@ -12,6 +12,20 @@ +
+ + +
diff --git a/main.js b/main.js index fdcc024..1fb3a7c 100644 --- a/main.js +++ b/main.js @@ -8,11 +8,12 @@ import getWMSLayer from "./wms"; import initPopover from "./popover"; import getWFSLayer from "./wfs"; import initInteractions from "./interactions"; +import initGazetteer from "./gazetteer"; // Create layer from imported functions const mastermapWMTS = await getWMTSLayer("os_licensed_background_colour"); -const woodlandWMS = getWMSLayer("sf_nwss"); -const mastermapWFS = getWFSLayer("osmm:osmm_topographicarea") +// const woodlandWMS = getWMSLayer("sf_nwss"); +// const mastermapWFS = getWFSLayer("osmm:osmm_topographicarea") // Set up a new Tile Layer const openStreetMap = new TileLayer({ @@ -28,7 +29,7 @@ const map = new Map({ // openStreetMap, mastermapWMTS, // woodlandWMS, - mastermapWFS, + // mastermapWFS, ], // A View object represents a simple 2D view of the map. // This is the object to act upon to change the center, resolution, and rotation of the map @@ -40,5 +41,15 @@ const map = new Map({ }), }); +// Zoom to +function zoomTo(coord_string) { + var split = coord_string.split(","); + if(split.length == 2) { + map.getView().setResolution(0.5); + map.getView().setCenter([parseInt(split[0]), parseInt(split[1])]); + } +} + // initPopover(map, woodlandWMS); -initInteractions(map); \ No newline at end of file +// initInteractions(map); +initGazetteer(zoomTo); diff --git a/style.css b/style.css index 79904ad..da17887 100644 --- a/style.css +++ b/style.css @@ -65,4 +65,14 @@ html, body { .ol-popup-closer:after { content: "✖"; color: black; -} \ No newline at end of file +} + +/* CSS for Gazetteer */ + +.gazetteer { + z-index: 1000; + position: absolute; + left: 5vw; + bottom: 10vh; + } + \ No newline at end of file