You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
575 lines
15 KiB
575 lines
15 KiB
var requestsGrid; |
|
var wfd; |
|
var legends = {}; |
|
var selectedEntityGroup = null; |
|
var selectedEntityId = null; |
|
var selectedMru = null; |
|
|
|
|
|
async function get_layer_list() { |
|
let response = await fetch(BASE_URL + '/src/geoserver/get_layers.php'); |
|
|
|
if (response.ok) { // if HTTP-status is 200-299 |
|
// get the response body (the method explained below) |
|
let json = await response.json(); |
|
return json |
|
} else { |
|
alert("HTTP-Error: " + response.status); |
|
} |
|
} |
|
|
|
|
|
async function fetchGeoJson(layerCode) { |
|
console.debug('fetching geojson...'); |
|
const url = BASE_URL + "/interface/geojson/" + layerCode; |
|
try { |
|
const response = await fetch(url); |
|
const data = await response.json(); |
|
console.debug('geojson data: ', data); |
|
return data; |
|
} catch (error) { |
|
console.error(error); |
|
} |
|
} |
|
|
|
|
|
function highlightFeature(e) { |
|
let overLayer = e.target; |
|
e.target.tempStyle = { |
|
weight: overLayer.options.weight, |
|
color: overLayer.options.color, |
|
dashArray: overLayer.options.dashArray, |
|
fillOpacity: overLayer.options.fillOpacity |
|
}; |
|
console.debug("highlighted: ", e.target); |
|
try { |
|
overLayer.setStyle({ |
|
weight: 5, |
|
color: '#666', |
|
dashArray: '', |
|
fillOpacity: 0.7 |
|
}); |
|
|
|
} catch (err) { |
|
console.log('could not change style'); |
|
} |
|
} |
|
|
|
|
|
function resetHighlight(e) { |
|
try { |
|
e.target.setStyle(e.target.tempStyle); |
|
delete e.target.tempStyle; |
|
} catch { |
|
console.debug('eee'); |
|
} |
|
} |
|
|
|
|
|
function onEachFeature(feature, layer) { |
|
layer.on({ |
|
mouseover: highlightFeature, |
|
mouseout: resetHighlight, |
|
click: zoomToFeature |
|
}); |
|
} |
|
|
|
|
|
function styleLine(feature, layer) { |
|
return { |
|
fillColor: getColor(), //feature.properties.name |
|
weight: 2, |
|
radius: 8, |
|
opacity: 1, |
|
color: '#000', |
|
dashArray: '3', |
|
fillOpacity: 0.8 |
|
}; |
|
} |
|
|
|
function stylePoint(feature, latlng) { |
|
console.debug(feature); |
|
return L.circleMarker(latlng, styleRules); |
|
}; |
|
|
|
|
|
function getColor(d=null) { |
|
if (d != null) |
|
return intToRGB(hashCode(d)); |
|
else |
|
return "#ff7800"; |
|
} |
|
|
|
|
|
function intToRGB(i){ |
|
var c = (i & 0x00FFFFFF) |
|
.toString(16) |
|
.toUpperCase(); |
|
|
|
return "00000".substring(0, 6 - c.length) + c; |
|
} |
|
|
|
|
|
function hashCode(str) { // java String#hashCode |
|
var hash = 0; |
|
for (var i = 0; i < str.length; i++) { |
|
hash = str.charCodeAt(i) + ((hash << 5) - hash); |
|
} |
|
return hash; |
|
} |
|
|
|
// zoom to feature (for data sources) |
|
function zoomToFeature(e) { |
|
let featureId = e.target.feature.properties.id; |
|
console.debug('feature zoomed: ', e.target); |
|
|
|
try { |
|
selectedEntityGroup = e.target.feature.id.split('.')[0]; |
|
selectedEntityId = e.target.feature.properties.id; |
|
} catch (error) { |
|
selectedEntityId = e.target.feature.properties.id; |
|
} |
|
lonlat = {lon: e.latlng.lng, lat: e.latlng.lat}; |
|
moreInfoPopup(e.target.feature.properties); |
|
|
|
try { |
|
mapL.fitBounds(e.target.getBounds()); |
|
} catch (err) { |
|
console.log('cannot zoom ', err); |
|
} |
|
} |
|
|
|
|
|
function boundsToExtent(northEast, southWest, my_crs) { |
|
let my_proj = my_crs.projection; |
|
let rt = my_proj.project(northEast); |
|
let lb = my_proj.project(southWest); |
|
|
|
return { |
|
left: lb.x, |
|
bottom: lb.y, |
|
right: rt.x, |
|
top: rt.y |
|
} |
|
} |
|
|
|
|
|
function getBathymetry() { |
|
// load contours in JSON |
|
const url = "https://ows.emodnet-bathymetry.eu/wfs?service=WFS&version=1.1.0&request=GetFeature&typeName=emodnet:contours&outputFormat=application/json"; |
|
const rainbow_url = "https://ows.emodnet-bathymetry.eu/wms"; |
|
let remoteLayer; |
|
// add rainbow colored bathymetry map |
|
const rnb = L.tileLayer.wms(rainbow_url, { transparent: true, layers: 'emodnet:mean_rainbowcolour', format: 'image/png'}); |
|
const cnt = L.tileLayer.wms(rainbow_url, { transparent: true, layers: 'emodnet:contours', format: 'image/png'}); |
|
|
|
legends['DPTH'] = L.control.Legend({ |
|
position: "bottomright", |
|
title: 'Bathymetry', |
|
symbolWidth: 150, |
|
symbolHeight: 208, |
|
collapsed: false, |
|
legends: [{ |
|
type: "image", |
|
label: ' ', |
|
url: "https://tiles.emodnet-bathymetry.eu/legends/legend_rainbow.png" |
|
}] |
|
}).addTo(mapL); |
|
remoteLayer = L.layerGroup([rnb, cnt]); |
|
|
|
return remoteLayer; |
|
} |
|
|
|
|
|
async function getDepthOnPoint(latlng) { |
|
await fetch(`https://rest.emodnet-bathymetry.eu/depth_sample?geom=POINT(${latlng.lng}%20${latlng.lat})`, { |
|
"credentials": "omit", |
|
"headers": { |
|
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:104.0) Gecko/20100101 Firefox/104.0", |
|
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8", |
|
"Accept-Language": "en-US,en;q=0.5", |
|
"Upgrade-Insecure-Requests": "1", |
|
"Sec-Fetch-Dest": "document", |
|
"Sec-Fetch-Mode": "navigate", |
|
"Sec-Fetch-Site": "same-site", |
|
"Sec-GPC": "1" |
|
}, |
|
"method": "GET", |
|
"mode": "cors" |
|
}).then(res => { |
|
return res.json(); |
|
}).then(depthInfo => { |
|
const depth = depthInfo.avg.toString(); |
|
L.popup() |
|
.setLatLng(latlng) |
|
.setContent(`<table class="table"><tr><th>Topography (m)</th></tr><tr><td>${depth}</td></tr></table>`) |
|
.openOn(mapL); |
|
}); |
|
} |
|
|
|
|
|
// function downloadStationData(stationid) { |
|
// console.debug('stationid: ', stationid); |
|
// if (stationid.length === 0) { |
|
// return; |
|
// } |
|
// fetch(`${BASE_URL}/src/data/get_station_data.php?id=${stationid}`, { |
|
// "credentials": "include", |
|
// "headers": { |
|
// "Accept": "application/zip", |
|
// "Accept-Language": "en-US,en;q=0.5", |
|
// "Sec-Fetch-Dest": "empty", |
|
// "Sec-Fetch-Mode": "cors", |
|
// "Sec-Fetch-Site": "same-origin", |
|
// "Pragma": "no-cache", |
|
// "Cache-Control": "no-cache" |
|
// }, |
|
// "method": "GET", |
|
// "mode": "cors" |
|
// }).then(res => { return res.blob(); }) |
|
// .then((data) => { |
|
// var a = document.createElement("a"); |
|
// a.href = window.URL.createObjectURL(data); |
|
// a.download = "request"; |
|
// a.click(); |
|
// }); |
|
// } |
|
|
|
|
|
// function downloadCruiseData(cruiseId) { |
|
// if (cruiseId.length === 0) { |
|
// return; |
|
// } |
|
// console.debug("CRUISE ID: ", cruiseId); |
|
// |
|
// fetch(`${BASE_URL}/src/data/get_cruise_data.php?id=${cruiseId}`, { |
|
// "credentials": "include", |
|
// "headers": { |
|
// "Accept": "application/zip", |
|
// "Accept-Language": "en-US,en;q=0.5", |
|
// "Sec-Fetch-Dest": "empty", |
|
// "Sec-Fetch-Mode": "cors", |
|
// "Sec-Fetch-Site": "same-origin", |
|
// "Pragma": "no-cache", |
|
// "Cache-Control": "no-cache" |
|
// }, |
|
// "method": "GET", |
|
// "mode": "cors" |
|
// }).then(res => { return res.blob(); }) |
|
// .then((data) => { |
|
// var a = document.createElement("a"); |
|
// a.href = window.URL.createObjectURL(data); |
|
// a.download = "request"; |
|
// a.click(); |
|
// }); |
|
// } |
|
|
|
|
|
function getHabitat(layerCode) { |
|
// load contours in JSON |
|
const url = "https://ows.emodnet-seabedhabitats.eu/geoserver/emodnet_view/wms"; |
|
const lgndUrl = "https://ows.emodnet-seabedhabitats.eu/geoserver/emodnet_view/ows?service=WMS&request=GetLegendGraphic&format=image%2Fpng&width=20&height=20&layer=eusm2021_bio_200&style=eusm2019_msfd_200" |
|
// add rainbow colored bathymetry map |
|
let habitats = new L.layerGroup(); |
|
const lrs = ['eusm2021_msfd_800', 'eusm2021_msfd_400', 'eusm2021_msfd_200']; |
|
let l; |
|
lrs.forEach(layer => { |
|
l = L.tileLayer.betterWms(url, { transparent: true, layers: layer, format: 'image/png'}); |
|
|
|
habitats.addLayer(l) |
|
}); |
|
|
|
legends[layerCode] = L.control.Legend({ |
|
position: "bottomright", |
|
symbolWidth: 400, |
|
symbolHeight: 600, |
|
collapsed: false, |
|
title: 'Habitat Type', |
|
legends: [{ |
|
type: "image", |
|
label: ' ', |
|
url: lgndUrl |
|
}] |
|
}).addTo(mapL); |
|
|
|
return habitats; |
|
} |
|
|
|
|
|
function moreInfoPopup(props) { |
|
let title; |
|
if (props.hasOwnProperty('code')) { |
|
title = `${props.code} — ${props.name}`; |
|
} else { |
|
title = `Grid — ${props.cellcode}`; |
|
} |
|
console.debug(props); |
|
// if (typeof props.code == 'undefined' && typeof props.name == 'undefined') |
|
if (typeof props.tspr !== 'undefined') { |
|
title = `POSEIDON — ${props.pid}`; |
|
props.entityGroup = 'POSEIDON'; |
|
} |
|
if (typeof props.ctStationCode !== 'undefined') |
|
title = `WFD — ${props.ctStationCode}`; |
|
|
|
Alpine.store('entity', props); |
|
getPagePartial('more-info').then(content => { |
|
new L.control.window(mapL, { |
|
title: title, |
|
content: `${content}`, |
|
visible: true, |
|
position: 'left' |
|
}); |
|
}); |
|
} |
|
|
|
|
|
function mruPopup(props) { |
|
if (props.hasOwnProperty('nssg')) { |
|
L.popup() |
|
.setLatLng([props.y_coord, props.x_coord]) |
|
.setContent(`<table class="table"><tr><th>NSSG Label</th></tr><tr><td>${props.nssg_label}</td></tr></table>`) |
|
.openOn(mapL); |
|
return; |
|
} |
|
let title; |
|
Alpine.store('mru', props); |
|
title = `MRU: ${props.mr_ms_aa}`; |
|
|
|
getPagePartial('mru-info').then(content => { |
|
content.props = props; |
|
new L.control.window(mapL, { |
|
title: title, |
|
content: `${content}`, |
|
visible: true, |
|
position: 'left' |
|
}); |
|
}); |
|
} |
|
|
|
|
|
// Fetches html from elements folder |
|
async function getPagePartial(partialName, target=null) { |
|
// const url = BASE_URL + `/src/Views/${partialName}.php`; |
|
const url = BASE_URL + `/interface/partial/${partialName}`; |
|
const res = await fetch(url) |
|
.then((response) => {return response.text();}) |
|
.then((content) => { |
|
return content |
|
}) |
|
.catch((err) => {return err;}); |
|
try { |
|
// fill target element with html |
|
document.querySelector(target).innerHTML = res; |
|
} catch(err) { |
|
return res; |
|
} |
|
} |
|
|
|
|
|
function getProduct(layer) { |
|
let url = layer.endpoint; |
|
let legendUrl = layer.legend; |
|
let l; |
|
|
|
l = L.tileLayer.betterWms(url, { transparent: true, layers: layer.code, format: 'image/png'}); |
|
legends[layer.code] = L.control.Legend({ |
|
position: "bottomright", |
|
symbolWidth: 100, |
|
symbolHeight: 200, |
|
collapsed: false, |
|
title: 'Probability of habitat presence', |
|
legends: [{ |
|
type: "image", |
|
label: ' ', |
|
url: legendUrl |
|
}] |
|
}).addTo(mapL); |
|
mapL.on('click', e => { |
|
let location = e.latlng; |
|
}); |
|
|
|
return l; |
|
} |
|
|
|
|
|
|
|
/** |
|
* Submit a request to the server and returns the entry inserted |
|
* @param {number} desc |
|
* @param {number} crit |
|
* @return {json} |
|
*/ |
|
// function request_data(desc, crit, from, to, bodyId=null) { |
|
// console.debug('requesting data'); |
|
// let url = BASE_URL + `/src/data/search_request_data.php?bodyid=${bodyId}&dateFrom=${from}&dateTo=${to}&criteria=${crit}`; |
|
// fetch(url) |
|
// .then(res => { |
|
// return res.json(); |
|
// }).then(data => { |
|
// db.requests.add({ |
|
// uuid: data.uuid, |
|
// filename: data.filename |
|
// }).then(d => { |
|
// requestsGrid.updateConfig({ |
|
// data: data |
|
// }).forceRender(); |
|
// }); |
|
// }); |
|
// } |
|
|
|
|
|
function initializeLayerTree() { |
|
pTree = new PickleTree({ |
|
c_target: 'layertree', //'maptab_treeview', |
|
c_config: { |
|
// options here |
|
switchMode: true, |
|
hasLink: true, |
|
drag: false, |
|
contextPos: 'before', |
|
foldedStatus: true |
|
}, |
|
switchCallback: layerTreeSwitch, |
|
c_data: myData |
|
}); |
|
} |
|
|
|
|
|
function getWFD(layerName, layerTitle) { |
|
const legendName = layerName.split('_').slice(1,3).join('_'); |
|
const lgndUrl = BASE_URL + "/img/legends/" + legendName + ".png"; |
|
console.debug(lgndUrl); |
|
let l; |
|
|
|
l = L.tileLayer.wms(BASE_URL + '/geoserver/wms', { transparent: true, layers: layerName, format: 'image/png'}); |
|
|
|
legends[layerName] = L.control.Legend({ |
|
position: "bottomright", |
|
title: layerTitle, |
|
symbolWidth: 90, |
|
symbolHeight: 130, |
|
collapsed: false, |
|
legends: [{ |
|
type: "image", |
|
label: '', |
|
url: lgndUrl |
|
}] |
|
}).addTo(mapL); |
|
|
|
return l; |
|
} |
|
|
|
|
|
async function searchForRequests() { |
|
let response = await fetch(BASE_URL + '/actions/requests'); |
|
|
|
if (response.ok) { // if HTTP-status is 200-299 |
|
// get the response body (the method explained below) |
|
let json = await response.json(); |
|
return json; |
|
} else { |
|
alert("HTTP-Error: " + response.status); |
|
} |
|
} |
|
|
|
|
|
function flattenJson(data, depth = 1) { |
|
var result = {}; |
|
function recurse(cur, prop) { |
|
if (Object(cur) !== cur || depth === 0) { |
|
result[prop] = cur; |
|
} else if (Array.isArray(cur)) { |
|
for(var i=0, l=cur.length; i<l; i++) |
|
recurse(cur[i], prop + "[" + i + "]"); |
|
if (l == 0) |
|
result[prop] = []; |
|
} else { |
|
var isEmpty = true; |
|
for (var p in cur) { |
|
isEmpty = false; |
|
recurse(cur[p], prop ? prop + "." + p : p, depth - 1); |
|
} |
|
if (isEmpty && prop) |
|
result[prop] = {}; |
|
} |
|
} |
|
recurse(data, "", depth); |
|
return result; |
|
} |
|
|
|
|
|
async function downloadShapefile(layerName, srs) { |
|
let response = await fetch(BASE_URL + '/geoserver/shapefile/' + layerName + '/' + srs, { |
|
"credentials": "include", |
|
"headers": { |
|
"Accept": "application/zip", |
|
"Accept-Language": "en-US,en;q=0.5", |
|
"Sec-Fetch-Dest": "empty", |
|
"Sec-Fetch-Mode": "cors", |
|
"Sec-Fetch-Site": "same-origin", |
|
"Pragma": "no-cache", |
|
"Cache-Control": "no-cache" |
|
}, |
|
"method": "GET", |
|
"mode": "cors" |
|
}); |
|
|
|
if (response.ok) { // if HTTP-status is 200-299 |
|
// get the response body (the method explained below) |
|
let zip = await response.blob(); |
|
var a = document.createElement("a"); |
|
let data = await zip; |
|
a.href = window.URL.createObjectURL(data); |
|
a.download = layerName + "_shapefiles"; |
|
a.click(); |
|
|
|
} else { |
|
alert("HTTP-Error: " + response.status); |
|
} |
|
} |
|
|
|
|
|
async function getFisheriesProduct() { |
|
// Create timeline slider control |
|
const group = L.layerGroup(); |
|
// load contours in JSON |
|
const bgLayer = L.tileLayer.betterWms(BASE_URL + '/geoserver/wms', { layers: 'nssg_areas', transparent: true, format: "image/png"}); |
|
const url = BASE_URL + "/interface/charts/afppy"; |
|
|
|
try { |
|
const response = await fetch(url); |
|
const data = await response.json(); |
|
let pies; |
|
// Add the custom control to the map |
|
pies = createPie(data, 1990).addTo(group); |
|
|
|
layerControls['AFPPY'] = L.control.slider(value => { |
|
pies.remove(); |
|
pies = createPie(data, value); |
|
group.addLayer(pies); |
|
},{ |
|
min: 1990, |
|
max: 2019, |
|
step: 1, |
|
value: 1990, |
|
logo: 'Year Selector', |
|
}).addTo(mapL); |
|
|
|
} catch (error) { |
|
console.error(error); |
|
} |
|
|
|
bgLayer.addTo(group); |
|
return group; |
|
} |
|
|
|
|
|
function getRandomColor() { |
|
var letters = '0123456789ABCDEF'; |
|
var color = '#'; |
|
for (var i = 0; i < 6; i++) { |
|
color += letters[Math.floor(Math.random() * 16)]; |
|
} |
|
return color; |
|
}
|
|
|