Skip to content

New Custom Map UI - GeoName Search #66

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Oct 26, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
329 changes: 329 additions & 0 deletions api/custom-map-ui/geoname-search-ui.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,329 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>GeoName Search</title>

<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-F3w7mX95PdgyTmZZMECAngseQB83DfGTowi0iMjiWaeVhAn4FJkqJByhZMI3AhiU" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js" integrity="sha384-/bQdsTh/da6pkI1MST/rWKFNjaCP5gBSY4sEBT38Q/9RBh9AH40zEOg7Hlq2THRZ" crossorigin="anonymous"></script>

<!--<script type="module" src="Web-Map-Custom-Element-0.8.0/mapml-viewer.js"></script>-->

<script type="module" src="../../dist/mapml-viewer.js"></script>
<style>
html, body {
height: 100%; /* These styles are required if you wish to use a % based
height value on the mapml-viewer element. */
}
mapml-viewer:defined {
width: 75%;
height: 90%;
}
h2 {
width: 100%;
text-align: center;
}
.result {
width: 100%;
background-color: #78bbc0;
color: white;
padding: 0.5em 1em;
text-decoration: none;
}
.result:hover {
background-color: #555;
}

.result:active {
background-color: black;
}

.result:visited {
background-color: #ccc;
}
.results_container {
overflow: scroll;
display:none;
height:100%;
}
.result_description {
font-size: 11px;
}
.search {
height:81%;
float:left;
}
</style>
</head>
<body>



<div class = "search">
<h2>GeoName Search</h2>

<input type="text" id="query" size="20%"/>
<button onclick="update()">Search</button>

<div id="results_count"></div>
<div id="results" class="results_container"></div>
</div>

<mapml-viewer projection="OSMTILE" zoom="4" lat="58.276703" lon="-103.710938" controls id="map">
<layer- label="OpenStreetMap" src="https://geogratis.gc.ca/mapml/en/osmtile/osm/" checked></layer->
</mapml-viewer>


<!-- Template layer to add to the mapml-viewer -->
<template id = "new_layer">
<layer- label="Test" checked="" id="layer">
<map-meta name="projection" content="OSMTILE"></map-meta>
<map-feature id="Test_Extent" class="child" zoom="2">
<map-featurecaption id="caption">Bounding Box Extent</map-featurecaption>
<map-geometry id="geom">
<map-polygon id="poly">
<map-coordinates id="coords"></map-coordinates>
</map-polygon>
</map-geometry>
<map-properties></map-properties>
</map-feature>
</layer->
</template>

<template id ="multi-linestring">
<map-linestring>
<map-coordinates id="coords"></map-coordinates>
</map-linestring>
</template>

<script>
// Select the mapml-viewer
mapp = document.querySelector("#map");
//mapp.zoomTo(5,6,10);

// Will store the json result
var placeholder = "";

// Computes the zoom extent based on bounding box's decimal degrees
// GetZoomExtent: listof(Num, Num, Num, Num) -> Int(3-16)
function GetZoomExtent (bbox) {
var x = [bbox[0], bbox[2]];
var y = [bbox[1], bbox[3]];
var difference = Math.max(Math.abs(x[0]-x[1]), Math.abs(y[0]-y[1])).toPrecision(2);

// choosing zoom level, based on the decimal degree extent
if (difference >=30) {
//console.log("zoom - 3, " + difference);
return 3;
} else if (difference >=25) {
//console.log("zoom - 4, " + difference);
return 4;
} else if (difference >= 10) {
//console.log("Zoom - 5, " + difference);
return 5;
} else if (difference >= 5) {
//console.log("zoom - 6, " + difference);
return 6;
} else if (difference >= 3) {
//console.log("zoom - 7, " + difference);
return 7;
} else if (difference >= 2) {
//console.log("zoom - 8, " + difference);
return 8;
} else if (difference >= 1) {
//console.log("zoom - 9, " + difference);
return 9;
} else if (difference >= 0.7) {
//console.log("zoom - 10, " + difference);
return 10;
} else if (difference >= 0.5) {
//console.log("zoom - 11, " + difference);
return 11;
} else if (difference >= 0.2) {
//console.log("zoom - 12, " + difference);
return 12;
} else if (difference >= 0.1) {
//console.log("zoom - 13, " + difference);
return 13;
} else if (difference == 0.04) { // Multipoint feature
//console.log("zoom (Multipoint Feature) - 10, " + difference);
return 10;
} else if (difference >= 0.05) {
//console.log("zoom - 14, " + difference);
return 14;
} else if (difference >= 0.02){
//console.log("zoom - 15, " + difference);
return 15;
} else {
//console.log("zoom - 16, " + difference);
return 16;
}
}

// Sorts GEOJSON to to be used by MapMl
// geojson2mapml: Str -> list(listof(list), Int(0-3))
async function geojson2mapml(url) {
let response = await fetch(url);
let data = await response.json();

arrs = data.geometry;

//console.log(data.geometry.type);
// Checking the type of feature
if (data.geometry.type == "MultiPolygon") {
return [arrs.coordinates, 1];
} else if (data.geometry.type == "MultiPoint") {
return [arrs.coordinates, 0];
} else if (data.geometry.type == "GeometryCollection") {
return [arrs.geometries, 2];
} else if (data.geometry.type == "MultiLineString") {
return [arrs.coordinates, 3];
} else {
return [arrs, data.geometry.type];
}

}

// Draws a new layer and moves the map to the layer
// map_pane: Int -> None
// Effects: Changes map's zoom and location. Also creates and adds a new layer to the map
async function map_pane(id) {
//console.log(id);
//console.log("Latitude: " + placeholder[id].latitude + ", Longitude: " + placeholder[id].longitude);
var feature_geojson = placeholder[id].feature.links.self.href + ".geojson";
console.log(feature_geojson);
//console.log(placeholder[id].bbox);

// zooming to location
var zoom = GetZoomExtent(placeholder[id].bbox);
mapp.zoomTo(placeholder[id].latitude, placeholder[id].longitude, zoom);

// Creating a new layer based on the template
var template = document.querySelector('#new_layer');
var clone = template.content.cloneNode(true);

// Setting Layer Name
var layer = clone.getElementById("layer");
layer.setAttribute("label", placeholder[id].name);

// Setting feature caption
var map_featurecaption = clone.getElementById("caption");
map_featurecaption.innerHTML = placeholder[id].name;

// Converting GeoJSON to MapML
var map_coordindates = clone.getElementById("coords");
//map_coordindates.innerHTML = placeholder[id].bbox[0] + " " + placeholder[id].bbox[1] + " " + placeholder[id].bbox[2] + " " + placeholder[id].bbox[3];

a = await geojson2mapml(feature_geojson);
//console.log(a);

// If it is a MultiPolygon
if (a[1] == 1) {
a = a[0][0][0];
out = ""
for (i = 0; i < a.length; i++) {
out = out + a[i][0] + " " + a[i][1] + " ";
}
//console.log(out);
map_coordindates.innerHTML = out;
} else if (a[1] == 0) { // If it is MultiPoint
out = a[0][0][0] + " " + a[0][0][1];
//console.log(a[0][0]);
map_coordindates.innerHTML = out;
} else if (a[1] == 2) { // If it is GeometryCollection
console.log("GeometryCollection", a);
alert("GeometryCollection not supported");

//for (i=0;i<a[0].length;i++) {
// var polygon_template = document.querySelector('#multi-linestring');
// var clone_polygon = polygon_template.content.cloneNode(true);
// out = "";
// var polygon_coordindates = clone_polygon.getElementById("coords");
//
// console.log(a[0][i].coordinates.length);
// for (y=0;y<a[0][i].coordinates.length;y++) {
// out = out + a[0][i].coordinates[y][0] + " " + a[0][i].coordinates[y][1] + " ";
// }
// console.log(out);
// ////////////////////////////////////////////////////
//}

} else if (a[1] == 3) { // If it is MultiLineString
//console.log(a);

var geom = clone.getElementById("geom");
//console.log(geom);

for (i=0;i<a[0].length;i++) {
var polygon_template = document.querySelector('#multi-linestring');
var clone_polygon = polygon_template.content.cloneNode(true);
out = "";
var polygon_coordindates = clone_polygon.getElementById("coords");

//console.log(a[0][i].length);
for (y=0;y<a[0][i].length;y++) {
out = out + a[0][i][y][0] + " " + a[0][i][y][1] + " ";
}

polygon_coordindates.innerHTML = out
//console.log(clone_polygon);
geom.appendChild(clone_polygon);
////////////////////////////////////////////////////
}

var poly = clone.getElementById("poly");
poly.parentNode.removeChild(poly);

//console.log(geom);


} else { // If feature is of any other type
console.log("Unsupported Type: " + a[1]);
alert("Unsupported Type: " + a[1]);
}
//console.log(map_coordindates.innerHTML);
// Add the newly created layer to mapmlviewer
//console.log(clone);
mapp.appendChild(clone);
}

// Display Search Results based on the search key term
// display_results: JSON -> None
// Effects: Populates the results container with search results
function display_results(obj) {
// Enable display panel
document.getElementById("results").style.display = "block";
for (var i=0; i < obj.length; i++) {
document.querySelector("#results").innerHTML = document.querySelector("#results").innerHTML + "<div class='result' onclick='map_pane(" + i + ")'>" + obj[i].name + "<div class='result_description'>" + obj[i].concise.code + " (" + obj[i].decision + ")</div></div>"
}
}

// Update Search Results based on the search Item, initiated when the "Search" button is pressed
// update: None -> None
// Effects: Makes an API Call to update global variable (placeholder) with JSON results, and updates the count of results found
function update() {
// update the extent
//<mapml-viewer>.zoom = 3;

// Reset the results
document.querySelector("#results").innerHTML = ""

var x = document.getElementById("query").value;
//console.log(x)
obj = ""
fetch('http://geogratis.gc.ca/services/geoname/en/geonames.json?q=' + x)
.then(response => response.json())
.then(json => {
document.querySelector("#results_count").innerHTML = json.items.length + " results found." + "<br><br>";

display_results(json.items);
placeholder = json.items;
//console.log(json);
})
}

</script>
</body>
</html>
1 change: 1 addition & 0 deletions api/custom-map-ui/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
<div class="navbar-nav">
<a class="nav-link active" href="#">Info <span class="sr-only">(current)</span></a>
<a class="nav-link" href="bootstrap-ui.html">Using Bootstrap</a>
<a class="nav-link" href="geoname-search-ui.html">Gazetteer (GeoName Search API)</a>
<a class="nav-link" href="#">Using Custom CSS</a>
</div>
</div>
Expand Down