diff --git a/web/maps/drawGoogleMap.js b/web/maps/drawGoogleMap.js index 7afed37f..c0a056d8 100755 --- a/web/maps/drawGoogleMap.js +++ b/web/maps/drawGoogleMap.js @@ -1,377 +1,72 @@ -// google.load('earth', '1'); -var map = null; -// var googleEarth; -var POINT_CUTOFF = 10000; -var calls = new Array(); -var the_infowindow = null; - - $(document).ready(function () { initialize(); }); - - function initialize() { - runThese(); - var mapOptions; - // googleEarth = new GoogleEarth(map); - the_infowindow = new google.maps.InfoWindow({ - content: "Loading..." - }); - } +// /web/maps/drawGoogleMap.js (Leaflet adapter) +(function (global) { + var calls = global.calls || (global.calls = []); + document.addEventListener("DOMContentLoaded", function () { + try { runThese(); } catch (e) { console.error("runThese() failed:", e); } + }); function runThese() { - for (var loop = 0; loop < calls.length; loop++) { - eval(calls[loop]); - } - } - - function getNewMap(mapType, divName) { - if (mapType == "big") { - mapOptions = { - zoom: 5, - center: new google.maps.LatLng((0,0) ,0), - mapTypeControl: true, - largeMapControl: true, - overviewMapControl: true, - overviewMapControlOptions:{opened:true}, - scaleControl: true, - streetViewControl: false, - mapTypeId: google.maps.MapTypeId.TERRAIN - }; - } else { - mapOptions = { - zoom: 5, - center: new google.maps.LatLng((0,0) ,0), - navigationControl: true, - navigationControlOptions: {style: google.maps.NavigationControlStyle.SMALL}, - mapTypeControl: false, - streetViewControl: false, - mapTypeId: google.maps.MapTypeId.TERRAIN - }; - } - map = new google.maps.Map(document.getElementById(divName), mapOptions); - } - - function forceIntoArray(theItem) { - if (!(theItem instanceof Array)) { - var temp = theItem; - theItem = new Array(); - theItem.push(temp); - } - return theItem; - } - - function drawGoogleMapSpecimens(mapType, divName, latArray, lonArray, nameArray, codeArray, imageArray, domainApp) { - /* Called from: - /mapComparison.do?subfamily=dolichoderinae&rank=subfamily&project=allantwebants&pr=b - /description.do?genus=azteca&species=alfari&rank=species&project=allantwebants - /bigMap.do?taxonName=dolichoderinaeazteca%20alfari&project=allantwebants - /fieldGuide.do?countryName=Bermuda&rank=species"); - /specimen.do?name=ufv-labecol-000383 - */ - //alert("drawGoogleMapSpecimens)"); - getNewMap(mapType, divName); - latArray = forceIntoArray(latArray); - lonArray = forceIntoArray(lonArray); - if ((map != null) && (latArray.length < POINT_CUTOFF)) { - var bounds = new google.maps.LatLngBounds(); - var point; - var marker; - var infoWindow = null; - var nameParts; - var nameUrl; - for (var i = 0; i < latArray.length; i++) { - point = new google.maps.LatLng(latArray[i], lonArray[i]); - bounds.extend(point); - var thisName = nameArray[i]; - var thisCode = codeArray[i]; - var thisImage = imageArray[i]; - var url = domainApp + "specimen.do?name=" + thisCode; - nameParts = thisName.split(" "); - nameUrl = domainApp + "description.do?rank=species&name=" + nameParts[1] + "&genus=" + nameParts[0]; - if (mapType == "big") { - infoWindow = infoWindowLayout(thisImage, nameUrl, thisName, url, thisCode); - // var kmlURL = $("#kmlURL").val(); - // var ctaLayer = new google.maps.KmlLayer( - // kmlURL, { - // preserveViewport : true - // }); - // ctaLayer.setMap(map); - } - marker = createMarker(map, point, url, infoWindow, mapType); - } - map.setCenter(bounds.getCenter(), "TERRAIN"); - - //alert("drawGoogleMapSpecimens() bounds:" + bounds + " zoom:" + map.getZoom()); - // This one seems to work well as is. - if (map.getZoom() > 5) { - map.setZoom(5); - } - if (i > 1) map.fitBounds(bounds); - - } - } - - function drawGoogleMapLocalities(mapType, divName, latArray, lonArray, nameArray, codeArray, domainApp) { //imageArray, - /* Called from: - Map constructed here: MapResultsAction.java. Map.getGoogleMapFunction writes this method call. - This will be displayed for locality count links on group.do pages. - */ - //alert("drawGoogleMapLocalities() map:" + map); - getNewMap(mapType, divName); - latArray = forceIntoArray(latArray); - lonArray = forceIntoArray(lonArray); - if ((map != null) && (latArray.length < POINT_CUTOFF)) { - - //alert("drawGoogleMapLocalities() map:" + map + " zoom:" + map.getZoom()); - - var bounds = new google.maps.LatLngBounds(); - var point; - var marker; - var infoWindow = null; - for (var i = 0; i < latArray.length; i++) { - point = new google.maps.LatLng(latArray[i], lonArray[i]); - bounds.extend(point); - var name = nameArray[i]; - var code = codeArray[i]; - var lat = latArray[i]; - var lon = lonArray[i]; - var url = getLocalityUrl(name, code, domainApp) - if (mapType == "big") { - infoWindow = infoWindowLocalityLayout(url, name, code, lat, lon); - } - marker = createMarker(map, point, url, infoWindow, mapType); - } - map.setCenter(bounds.getCenter(), "TERRAIN"); - - //alert("drawGoogleMapLocalities() bounds:" + bounds + " zoom:" + map.getZoom()); - // This one seems to work well as is. - if (map.getZoom() >= 5) { - map.setZoom(5); - } - -/* -Utah localities look great: - http://localhost/antweb/advancedSearch.do?searchMethod=advancedSearch&advanced=true&family=Formicidae&groupName=University%20of%20Utah&output=mapLocality - drawGoogleMapLocalities() bounds:((-13, -110.40116999999998), (35.2, 142.29663000000005)) zoom:5 -Field Museum do not: - http://localhost/antweb/advancedSearch.do?searchMethod=advancedSearch&advanced=true&family=Formicidae&groupName=Field%20Museum&output=mapLocality - drawGoogleMapLocalities() bounds:((-38.416096, 98.81666599999994), (60.416023, 80.63373000000001)) zoom:5 - - Don't seem able to force... - - Seems here that zoom level is ignored if there are bounds. Have not found a good - bounds setting so that the map is displayed at global level. Still getting - multiple globes on a map. Boo. - // bounds:((-38.416096, 98.81666599999994), (60.416023, 80.63373000000001) - - var bigBounds = new google.maps.LatLngBounds(); - pointA = new google.maps.LatLng(-13, -110.40116999999998); - pointB = new google.maps.LatLng(35.2, 142.29663000000005); - bigBounds.extend(pointA); - bigBounds.extend(pointB); - map.fitBounds(bigBounds); -*/ - if (i > 1) map.fitBounds(bounds); - - } else { - alert("drawGoogleMapLocalities() else"); - - } - //console.log("drawGoogleMapLocalities() i:" + latArray.length + " cutoff:" + POINT_CUTOFF); - } - - function drawGoogleMapLocality(mapType, divName, latArray, lonArray, nameArray, codeArray, domainApp) { - /* Called from: - /locality.do?name=JTL022303 - /bigMap.do?locality=JTL022303&project=allantwebants"); - */ - //alert("drawGoogleMapLocality()"); - //console.log("drawGoogleMapLocality()"); - getNewMap(mapType, divName); - latArray = forceIntoArray(latArray); - lonArray = forceIntoArray(lonArray); - if ((map != null) && (latArray.length < POINT_CUTOFF)) { - var bounds = new google.maps.LatLngBounds(); - var point; - var marker; - var infoWindow = null; - var nameUrl; - var thisImage; - for (var i = 0; i < latArray.length; i++) { - point = new google.maps.LatLng(latArray[i], lonArray[i]); - bounds.extend(point); - var name = nameArray[i]; - var code = codeArray[i]; - var lat = latArray[i]; - var lon = lonArray[i]; - var url = getLocalityUrl(name, code, domainApp) - if (mapType == "big") { - infoWindow = infoWindowLocalityLayout(url, name, code, lat, lon); - //alert("drawGoogleMapLocality() infoWindow:" + infoWindow); - } - marker = createMarker(map,point,url,infoWindow,mapType); - } - - //alert("drawGoogleMapLocality() bounds:" + bounds + " zoom:" + map.getZoom()); - map.setZoom(7); -/* - if (map.getZoom() > 5) { - map.setZoom(5); - } - map.fitBounds(bounds); // If the bounds are just a point it will be a very small box. -*/ - map.setCenter(bounds.getCenter(), "TERRAIN"); - } - } - - function drawGoogleMapCollection(mapType, divName, latArray, lonArray, codeArray, domainApp) { - /* Called from: - /collection.do?name=Wm-B-05-2-01"); - */ - //alert("drawGoogleMapCollection()"); - getNewMap(mapType, divName); - latArray = forceIntoArray(latArray); - lonArray = forceIntoArray(lonArray); - if ((map != null) && (latArray.length < POINT_CUTOFF)) { - var bounds = new google.maps.LatLngBounds(); - var point; - var marker; - var infoWindow = null; - var nameParts; - var nameUrl; - var thisImage; - for (var i = 0; i < latArray.length; i++) { - point = new google.maps.LatLng(latArray[i], lonArray[i]); - bounds.extend(point); - var thisCode = codeArray[i]; - var thisLat = latArray[i]; - var thisLon = lonArray[i]; - var url = domainApp + "collection.do?name=" + thisCode; - if (mapType == "big") { - infoWindow = infoWindowCollectionLayout(url, thisCode, thisLat, thisLon); - } - marker = createMarker(map,point,url,infoWindow,mapType); - } - - map.setZoom(7); - /* - if (map.getZoom() > 5) { - map.setZoom(5); - } - map.fitBounds(bounds); - */ - - map.setCenter(bounds.getCenter(), "TERRAIN"); - } - } - - function drawGoogleMap(mapType, divName, latArray, lonArray) { - getNewMap(mapType, divName); - if ((map != null) && (latArray.length < POINT_CUTOFF)) { - var bounds = new google.maps.LatLngBounds(); - var point; - var marker; - for (var i = 0; i < latArray.length; i++) { - var properties = { - point: new google.maps.LatLng(latArray[i], lonArray[i]), - map:map, - icon:"/maps/new_icon4.png" - }; - bounds.extend(point); - newMarker = new google.maps.Marker(properties); - markers.push(newMarker); - } - if (map.getZoom() > 5) { - map.setZoom(5); - } - map.fitBounds(bounds); - map.setCenter(bounds.getCenter(), "TERRAIN"); + for (var i = 0; i < calls.length; i++) { + try { /* eslint no-eval:0 */ eval(calls[i]); } + catch (e) { console.error("Error in calls["+i+"]: ", calls[i], e); } } } - function drawGoogleMapSinglePoint(mapType, divName, lat, lon, nameArray, codeArray, imageArray) { - getNewMap(mapType, divName); - if (map != null) { - var bounds = new google.maps.LatLngBounds(); - var point = new google.maps.LatLng(lat, lon); - bounds.extend(point); - map.addOverlay(new google.maps.Marker(point)); - if (map.getZoom() > 5) { - map.setZoom(5); - } - map.fitBounds(bounds); - map.setCenter(bounds.getCenter(), "TERRAIN"); + function toArray(x) { return Array.isArray(x) ? x : [x]; } + function toNumArray(a) { return toArray(a).map(function (v) { return parseFloat(v); }); } + function need(fnName) { + if (typeof global[fnName] !== "function") { + console.error(fnName+" not available. Did /sdk/drawMap.js load from the microservice?"); + return false; } + return true; } - function createMarker(map,point,url,infoWindow,mapType) { - var imageUrl = '/maps/new_icon4.png'; - var markerImage = new google.maps.MarkerImage(imageUrl, new google.maps.Size(10, 10)); - var marker = new google.maps.Marker({ - position: point, - map: map, - icon: markerImage - }); - if (mapType == "big") { - var contentString = infoWindow; - if (infoWindow != null) { - google.maps.event.addListener(marker, "click", function () { - the_infowindow.setContent(infoWindow); - the_infowindow.setPosition(point); - the_infowindow.open(map, this); - }); - } - } - } - - function infoWindowLayout(image,nameUrl,name,url,code) { - infoWindow = "
"; - if (image.length > 0) { - infoWindow += "
"; - } else { - infoWindow += ""; - } - infoWindow += "Species: " + name + "
"; - infoWindow += "Specimen: " + code + ""; - infoWindow += "
"; - return infoWindow; - } - - function getLocalityUrl(name, code, domainApp) { - code = code.replace(/\+/g, '%20'); // 'Friday%20September%2013th' - code = decodeURIComponent(code); - name = name.replace(/\+/g, '%20'); // 'Friday%20September%2013th' - name = decodeURIComponent(name); - var url = domainApp; - if (code !== null && code !== "null") { - url += "locality.do?code=" + code; - } else if (name !== null) { - url += "locality.do?name=" + name; - } else { - return null; - } - return url; - } - - function infoWindowLocalityLayout(url, name, code, lat, lon) { - code = code.replace(/\+/g, '%20'); // 'Friday%20September%2013th' - code = decodeURIComponent(code); - name = name.replace(/\+/g, '%20'); // 'Friday%20September%2013th' - name = decodeURIComponent(name); - if (name === null || name === "null") name = code; - - infoWindow = "
"; - infoWindow += "Locality: " + name + "
"; - infoWindow += "Latitude: " + lat + "
"; - infoWindow += "Longitude: " + lon + "
"; - infoWindow += "
"; - return infoWindow; - } - - function infoWindowCollectionLayout(url,code,lat,lon) { - infoWindow = "
"; - infoWindow += "Collection: " + code + "
"; - infoWindow += "Latitude: " + lat + "
"; - infoWindow += "Longitude: " + lon + "
"; - infoWindow += "
"; - return infoWindow; - } - + // Simple coordinate arrays + global.drawGoogleMap = function (mapType, divName, latArray, lonArray) { + var lats = toNumArray(latArray), lons = toNumArray(lonArray); + if (!lats.length || !lons.length) return; + if (!need("drawMap")) return; + global.drawMap(divName, lats, lons); + }; + + // Localities (name + code) + global.drawGoogleMapLocalities = function (mapType, divName, latArray, lonArray, nameArray, codeArray) { + var lats = toNumArray(latArray), lons = toNumArray(lonArray); + var names = toArray(nameArray||[]), codes = toArray(codeArray||[]); + if (need("drawMapLocalities")) global.drawMapLocalities(divName, lats, lons, names, codes); + else if (need("drawMap")) global.drawMap(divName, lats, lons); + }; + + // Locality (singular) + global.drawGoogleMapLocality = function (mapType, divName, latArray, lonArray, nameArray, codeArray) { + global.drawGoogleMapLocalities(mapType, divName, latArray, lonArray, nameArray, codeArray); + }; + + // Specimens (name + code + optional image) + global.drawGoogleMapSpecimens = function (mapType, divName, latArray, lonArray, nameArray, codeArray, imageArray) { + var lats = toNumArray(latArray), lons = toNumArray(lonArray); + var names = toArray(nameArray||[]), codes = toArray(codeArray||[]), imgs = toArray(imageArray||[]); + if (need("drawMapSpecimens")) global.drawMapSpecimens(divName, lats, lons, names, codes, imgs); + else if (need("drawMapLocalities")) global.drawMapLocalities(divName, lats, lons, names, codes); + else if (need("drawMap")) global.drawMap(divName, lats, lons); + }; + + // Collections (codes only) + global.drawGoogleMapCollection = function (mapType, divName, latArray, lonArray, codeArray) { + var codes = toArray(codeArray||[]); + global.drawGoogleMapLocalities(mapType, divName, latArray, lonArray, codes, codes); + }; + + // Single point + global.drawGoogleMapSinglePoint = function (mapType, divName, lat, lon, nameArray, codeArray, imageArray) { + var name = Array.isArray(nameArray)? nameArray[0] : nameArray; + var code = Array.isArray(codeArray)? codeArray[0] : codeArray; + var img = Array.isArray(imageArray)? imageArray[0] : imageArray; + var latNum = parseFloat(lat), lonNum = parseFloat(lon); + if (isNaN(latNum)||isNaN(lonNum)) return; + + if (need("drawMapSinglePoint")) global.drawMapSinglePoint(divName, latNum, lonNum, name||"", code||"", img||""); + else if (need("drawMap")) global.drawMap(divName, [latNum], [lonNum]); + }; +})(window); diff --git a/web/maps/googleMapPreInclude.jsp b/web/maps/googleMapPreInclude.jsp index 1613a7fb..1b3607cb 100644 --- a/web/maps/googleMapPreInclude.jsp +++ b/web/maps/googleMapPreInclude.jsp @@ -1,17 +1,20 @@ +<%-- /web/maps/googleMapPreInclude.jsp (Leaflet) --%> +<% + // Point this to YOUR existing microservice + final String MAPS_BASE = "http://localhost:8081"; +%> +<% if (!HttpUtil.isBot(request)) { %> + + + + - - -<% if (!HttpUtil.isBot(request)) { + + - String googleMapKey = AntwebProps.getGoogleMapKey(); - //A.log("googleMapPreInclude.jsp googleMapKey:" + googleMapKey); -%> + + - - - + - <% } %> - - \ No newline at end of file diff --git a/web/maps/sdk/drawMap.js b/web/maps/sdk/drawMap.js new file mode 100644 index 00000000..5797ca5b --- /dev/null +++ b/web/maps/sdk/drawMap.js @@ -0,0 +1,118 @@ +(function (global) { + // ---- SETTINGS ---- + const USE_CLUSTER = false; // set to true if you ever want the numeric balloons back + const DOT_STYLE = { + radius: 5, + color: "#ffffff", // white border stroke + weight: 2, // thicker border + fillColor: "#ff3b3b", // inner red + fillOpacity: 1 + }; + + + let map = null; + let layer = null; // LayerGroup (no cluster) OR MarkerClusterGroup + let dots = []; // keep references to markers for fitBounds() + + function ensureMap(divName, lat, lon, zoom) { + if (map) return map; + + let el = document.getElementById(divName) || + document.getElementById("map") || + document.getElementById("map-canvas"); + if (!el) { + el = document.createElement("div"); + el.id = divName || "map"; + el.style.height = "500px"; + el.style.width = "100%"; + document.body.appendChild(el); + } + + const cfg = global.__MAP_SVC_CFG__ || {}; + const tileUrl = cfg.TILE_URL || "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"; + const tileAttr = cfg.TILE_ATTR || "© OpenStreetMap contributors"; + + // preferCanvas makes thousands of circleMarkers smooth + map = L.map(el, { preferCanvas: true }) + .setView([parseFloat(lat) || 0, parseFloat(lon) || 0], zoom || 2); + + L.tileLayer(tileUrl, { maxZoom: 19, attribution: tileAttr }).addTo(map); + + layer = USE_CLUSTER + ? L.markerClusterGroup({ chunkedLoading: true }) + : L.layerGroup(); + + map.addLayer(layer); + return map; + } + + function addDot(lat, lon, html) { + if (lat == null || lon == null) return null; + const y = parseFloat(lat), x = parseFloat(lon); + if (Number.isNaN(y) || Number.isNaN(x)) return null; + + // circleMarker = small red dot (no default pin, no numbers) + const m = L.circleMarker([y, x], DOT_STYLE); + if (html) m.bindPopup(html); + layer.addLayer(m); + dots.push(m); + return m; + } + + function fitToDots(padding) { + if (!dots.length) return; + const group = L.featureGroup(dots); + map.fitBounds(group.getBounds(), { padding: padding || [30, 30] }); + } + + // ---- Public API (keeps your current function names) ---- + global.drawMap = function (divName, latArray, lonArray) { + const lat0 = latArray?.length ? parseFloat(latArray[0]) : 0; + const lon0 = lonArray?.length ? parseFloat(lonArray[0]) : 0; + ensureMap(divName, lat0, lon0, 5); + + const n = Math.min(latArray?.length || 0, lonArray?.length || 0); + for (let i = 0; i < n; i++) addDot(latArray[i], lonArray[i]); + fitToDots(); + }; + + global.drawMapLocalities = function (divName, latArray, lonArray, nameArray, codeArray) { + const lat0 = latArray?.length ? parseFloat(latArray[0]) : 0; + const lon0 = lonArray?.length ? parseFloat(lonArray[0]) : 0; + ensureMap(divName, lat0, lon0, 5); + + const n = Math.min(latArray?.length || 0, lonArray?.length || 0); + for (let i = 0; i < n; i++) { + const name = (nameArray && nameArray[i]) || ""; + const code = (codeArray && codeArray[i]) || ""; + const html = `
Locality: ${name}
Code: ${code}
`; + addDot(latArray[i], lonArray[i], html); + } + fitToDots(); + }; + + global.drawMapSpecimens = function (divName, latArray, lonArray, nameArray, codeArray, imageArray) { + const lat0 = latArray?.length ? parseFloat(latArray[0]) : 0; + const lon0 = lonArray?.length ? parseFloat(lonArray[0]) : 0; + ensureMap(divName, lat0, lon0, 5); + + const n = Math.min(latArray?.length || 0, lonArray?.length || 0); + for (let i = 0; i < n; i++) { + const name = (nameArray && nameArray[i]) || ""; + const code = (codeArray && codeArray[i]) || ""; + const img = (imageArray && imageArray[i]) || ""; + const imgTag = img ? `
` : ""; + const html = `
Specimen: ${name}
Code: ${code}${imgTag}
`; + addDot(latArray[i], lonArray[i], html); + } + fitToDots(); + }; + + global.drawMapSinglePoint = function (divName, lat, lon, name, code, img) { + ensureMap(divName, parseFloat(lat) || 0, parseFloat(lon) || 0, 8); + const imgTag = img ? `
` : ""; + const html = `
${name || ""}
${code || ""}${imgTag}
`; + addDot(lat, lon, html); + fitToDots(); + }; +})(window); diff --git a/web/maps/sdk/index.html b/web/maps/sdk/index.html new file mode 100644 index 00000000..9b7c6dbb --- /dev/null +++ b/web/maps/sdk/index.html @@ -0,0 +1,16 @@ + + +SDK + + +

Map SDK

+

Include these in your app:

+
<link rel="stylesheet" href="https://YOUR-MAPS-APP/sdk/leaflet.css">
+<link rel="stylesheet" href="https://YOUR-MAPS-APP/sdk/MarkerCluster.css">
+<link rel="stylesheet" href="https://YOUR-MAPS-APP/sdk/MarkerCluster.Default.css">
+<script src="https://YOUR-MAPS-APP/sdk/leaflet.js"></script>
+<script src="https://YOUR-MAPS-APP/sdk/leaflet.markercluster.js"></script>
+<script src="https://YOUR-MAPS-APP/sdk/config.js"></script>
+<script src="https://YOUR-MAPS-APP/sdk/drawMap.js"></script>
+ + diff --git a/web/maps/widget/index.html b/web/maps/widget/index.html new file mode 100644 index 00000000..a39d071c --- /dev/null +++ b/web/maps/widget/index.html @@ -0,0 +1,51 @@ + + + + + Map Widget + + + + + + + +
+ + + + + +