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" ,
symbolWidth : 150 ,
symbolHeight : 208 ,
collapsed : true ,
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 : true ,
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 : true ,
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 ) {
const legendName = layerName . split ( '_' ) . slice ( 1 , 3 ) . join ( '_' ) ;
const lgndUrl = BASE _URL + "/images/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" ,
symbolWidth : 90 ,
symbolHeight : 130 ,
collapsed : true ,
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 ;
}