diff options
Diffstat (limited to 'main.js')
-rw-r--r-- | main.js | 4320 |
1 files changed, 611 insertions, 3709 deletions
@@ -29,27 +29,18 @@ import ScaleLine from 'ol/control/ScaleLine.js'; import Zoom from 'ol/control/Zoom.js'; import ZoomSlider from 'ol/control/ZoomSlider.js'; -import Overlay from 'ol/Overlay.js'; - import MVT from 'ol/format/MVT.js'; import VectorTileLayer from 'ol/layer/VectorTile.js'; import VectorTile from 'ol/source/VectorTile.js'; import { createXYZ } from 'ol/tilegrid.js'; -import VectorLayer from 'ol/layer/Vector.js'; -import VectorSource from 'ol/source/Vector.js'; - import { toContext } from 'ol/render.js'; import Polygon from 'ol/geom/Polygon.js'; import LineString from 'ol/geom/LineString.js'; import Point from 'ol/geom/Point.js'; -import CircleStyle from 'ol/style/Circle.js'; import Fill from 'ol/style/Fill.js'; import Icon from 'ol/style/Icon.js'; -import RegularShape from 'ol/style/RegularShape.js'; -import Stroke from 'ol/style/Stroke.js'; -import Style from 'ol/style/Style.js'; import proj4 from 'proj4'; import { get as getProjection } from 'ol/proj.js'; @@ -57,8 +48,9 @@ import { register as registerProjection } from 'ol/proj/proj4.js'; import { Modal, Popover } from 'bootstrap'; -import './style.css'; - +import { layers } from './src/layers.js'; +import { popover } from './src/popover.js'; +import './src/style.css'; proj4.defs('EPSG:3006', '+proj=utm +zone=33 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs +type=crs'); registerProjection(proj4); @@ -126,6 +118,65 @@ const view = new View({ constrainResolution: false, }); +const age_filter_settings = { + active: false, + type: 'relative', + operator: '<=', + quantity: 1, + unit: 'y', + show_unknown: false, + get_relative_date: function(quantity, unit) { + if (quantity == null || isNaN(quantity) || unit == null) { + return null; + } + /* use today noon localtime to avoid issues due to DST when substracting dates */ + const d = new Date(); + d.setHours(12, 0, 0, 0); + switch (unit) { + case 'd': + d.setDate(d.getDate() - quantity); + break; + case 'w': + d.setDate(d.getDate() - 7 * quantity); + break; + case 'm': + d.setMonth(d.getMonth() - quantity); + break; + case 'y': + d.setFullYear(d.getFullYear() - quantity); + break; + default: + return null; + } + return d; + }, + _min_ts: null, + _max_ts: null, + _date_to_ts: function(d) { + if (d == null) { + return null; + } + /* number of days since 1970-01-01; take both dates at 00:00:00.0 UTC */ + return Math.floor(Date.UTC(d.getFullYear(), d.getMonth(), d.getDate())/86_400_000); + }, + setup_minmax: function() { + this._min_ts = this._max_ts = null; + switch (this.type) { + case 'relative': { + const date = this.get_relative_date(this.quantity, this.unit); + const prop = {'<=':'_min_ts', '>=':'_max_ts'}[this.operator]; + this[prop] = this._date_to_ts(date); + break; + } + case 'interval': { + this._min_ts = this._date_to_ts(this.from); + this._max_ts = this._date_to_ts(this.to); + break; + } + } + }, +}; + let baseMapLayer = 'topowebb_nedtonad'; (function() { const params = new URLSearchParams(window.location.hash.substring(1)); @@ -165,6 +216,51 @@ let baseMapLayer = 'topowebb_nedtonad'; baseMapLayer = params.get('basemap'); } baseMapSource.setUrl(`https://minkarta.lantmateriet.se/map/topowebbcache?LAYER=${encodeURIComponent(baseMapLayer)}`); + + if (params.has('age-filter')) { + (function(param) { + if (param === '') { + return; + } + /* eslint-disable-next-line no-useless-escape */ + const m0 = /^([ +\-]?)([0-9]+)([dwmy])$/.exec(param); + if (m0 != null) { + age_filter_settings.type = 'relative'; + age_filter_settings.operator = (m0[1] === ' ' || m0[1] === '+' || m0[1] === '') ? '>=' + : m0[1] === '-' ? '<=' + : null; + age_filter_settings.quantity = parseInt(m0[2], 10); + age_filter_settings.unit = m0[3]; + age_filter_settings.setup_minmax(); + age_filter_settings.active = true; + return; + } + const m1 = /^([0-9]{8})-([0-9]{8})$/.exec(param); /* YYYYMMDD */ + if (m1 != null) { + const parse_date = (m) => new Date( + parseInt(m.slice(0,4), 10), + parseInt(m.slice(4,6), 10)-1, + parseInt(m.slice(6,8), 10), + 12 /* use 12:00:00.0 like for the <input type="date"> */ + ); + age_filter_settings.type = 'interval'; + age_filter_settings.from = parse_date(m1[1]); + age_filter_settings.to = parse_date(m1[2]); + age_filter_settings.setup_minmax(); + age_filter_settings.active = true; + return; + } + console.log(`Ignoring invalid value for 'age-filter' parameter: ${param}`); + })(params.get('age-filter')); + } + if (params.has('show-unknown-age')) { + const param = params.get('show-unknown-age'); + if (param === '0') { + age_filter_settings.show_unknown = false; + } else if (param === '1') { + age_filter_settings.show_unknown = true; + } + } })(); @@ -187,11 +283,21 @@ const container = document.getElementById('map-control-container'); const container0 = map.getViewport().getElementsByClassName('ol-overlaycontainer-stopevent')[0]; container0.appendChild(document.getElementById('zoom-control')); container0.appendChild(container); - container0.appendChild(document.getElementById('modal-info')); - - const backdrop = document.createElement('div'); - container0.appendChild(backdrop); - backdrop.id = 'modal-info-backdrop'; + container0.appendChild(document.getElementById('info-modal')); + + const info_backdrop = document.createElement('div'); + container0.appendChild(info_backdrop); + info_backdrop.id = 'info-modal-backdrop'; + + const age_filter = document.createElement('div'); + age_filter.id = 'age-filter-modal'; + age_filter.classList.add('modal'); + age_filter.setAttribute('tabindex', '-1'); + age_filter.setAttribute('aria-hidden', 'true'); + container0.appendChild(age_filter); + const age_filter_backdrop = document.createElement('div'); + age_filter_backdrop.id = 'age-filter-modal-backdrop'; + container0.appendChild(age_filter_backdrop); })(); /* zoom in/out */ @@ -263,7 +369,7 @@ if (window.location !== window.parent.location) { btn.appendChild(i); i.classList.add('bi', 'bi-box-arrow-up-right'); - btn.onclick = function(event) { + btn.onclick = function() { const coordinates = view.getCenter(); const url = new URL(window.location.href); const searchParams = new URLSearchParams(url.hash.substring(1)); @@ -280,6 +386,7 @@ if (window.location === window.parent.location) { const buttons = Object.fromEntries([ {id: 'layer-selection', title: 'Lagerval', bi: 'stack'}, {id: 'map-legend', title: 'Teckenförklaring', bi: 'list-task'}, + {id: 'age-filter', title: 'Filtrera objekt efter ålder', bi: 'clock-history'}, ].map(function(x) { const div = document.createElement('div'); menu.appendChild(div); @@ -302,8 +409,11 @@ if (window.location === window.parent.location) { Object.keys(buttons).forEach(function(id) { const panel = document.getElementById(id + '-panel'); + if (panel == null) { + return; + } const btn = buttons[id]; - btn.onclick = function(event) { + btn.onclick = function() { if (btn.getAttribute('aria-expanded') === 'true') { panel.setAttribute('aria-hidden', 'true'); btn.setAttribute('aria-expanded', 'false'); @@ -350,11 +460,8 @@ if (window.location === window.parent.location) { control.addEventListener('enterfullscreen', function() { featureOverlayLayer.setVisible(false); - const popover = Popover.getInstance(popup); - if (popover !== null) { - /* dispose popover as entering fullscreen messes up its position */ - popover.dispose(); - } + /* dispose popover as entering fullscreen messes up its position */ + Popover.getInstance(popup)?.dispose(); const btn = control.element.getElementsByTagName('button')[0]; btn.classList.replace(classInactive, classActive); @@ -369,11 +476,8 @@ if (window.location === window.parent.location) { }) control.addEventListener('leavefullscreen', function() { featureOverlayLayer.setVisible(false); - const popover = Popover.getInstance(popup); - if (popover !== null) { - /* dispose popover as is might overflow the viewport */ - popover.dispose(); - } + /* dispose popover as is might overflow the viewport */ + Popover.getInstance(popup)?.dispose(); const btn = control.element.getElementsByTagName('button')[0]; btn.classList.replace(classActive, classInactive); @@ -405,7 +509,7 @@ if (window.location === window.parent.location) { i.classList.add('bi', 'bi-download'); menu.appendChild(div); - btn.onclick = function(event) { + btn.onclick = function() { map.once('rendercomplete', function() { const canvas0 = document.createElement('canvas'); const size = map.getSize(); @@ -457,13 +561,13 @@ if (window.location === window.parent.location) { btn.appendChild(i); i.classList.add('bi', 'bi-info-lg'); - const panel = document.getElementById('modal-info'); + const panel = document.getElementById('info-modal'); const modal = new Modal(panel, { backdrop: false, }); - const backdrop = document.getElementById('modal-info-backdrop'); - backdrop.onclick = function(event) { + const backdrop = document.getElementById('info-modal-backdrop'); + backdrop.onclick = function() { modal.hide(); }; @@ -506,11 +610,11 @@ if (window.location === window.parent.location) { }); }); - btn.onclick = function(event) { + btn.onclick = function() { infoMetadataAccordions.forEach((x) => x.element.replaceChildren()); modal.show(); Promise.allSettled(Object.entries(mapLayers).map(function([grp,lyr]) { - if (lyr != null && lyr.getSource() instanceof VectorTile) { + if (lyr?.getSource() instanceof VectorTile) { const url = lyr.getSource().getUrls()[0]; if (url == null || url.length <= 16 || url.substr(url.length - 16) !== '/{z}/{x}/{y}.pbf') { return new Promise(() => { throw new Error(`Invalid URL ${url}`); }); @@ -540,7 +644,7 @@ if (window.location === window.parent.location) { const ul = x.element; const groupnames = new Set(); const last_updated = []; - x.items.forEach(function([groupname, _]) { + x.items.forEach(function([groupname]) { const layer_group = metadata[groupname]; if (layer_group == null) { return; @@ -574,11 +678,11 @@ if (window.location === window.parent.location) { x.items.forEach(function([groupname, layername]) { /* for each source file associated with the accordion header, show copyright, license and timing information */ const layer_group = metadata[groupname]; - if (layer_group == null || layer_group.layers == null || layer_group.source_files == null) { + if (layer_group?.layers == null || layer_group?.source_files == null) { return; } const def = layer_group.layers[layername]; - if (def == null || def.source_files == null) { + if (def?.source_files == null) { return; } def.source_files.forEach(function(source_file) { @@ -675,12 +779,9 @@ if (window.location === window.parent.location) { /* we're all set, show the control container now */ container.setAttribute('aria-hidden', 'false'); -view.on('change', function(event) { +view.on('change', function() { featureOverlayLayer.setVisible(false); - const popover = Popover.getInstance(popup); - if (popover !== null) { - popover.dispose(); - } + Popover.getInstance(popup)?.dispose(); const coordinates = view.getCenter(); const searchParams = new URLSearchParams(location.hash.substring(1)); @@ -690,3278 +791,6 @@ view.on('change', function(event) { location.hash = '#' + searchParams.toString(); }); - -/* TODO: this should really be refactored… */ -const layers = { - 'mrr.appr_ec': { - popoverTitle: 'Bearbetningskoncession \u2013 beviljad', - popover: [ - ['Namn', 'name'], - ['Koncessionsmineral', 'mineral'], - ['Ägare', 'owners'], - ['Tillståndsid', 'licenceid', { classes: ['feature-attr-mrr-license-id'] }], - ['Areal', 'geom_area', { fn: 'area' }], - ['Giltig från', 'validfrom'], - ['Giltig till', 'validto'], - ['Diarienummer', 'diarynr', { classes: ['feature-attr-dnr'] }], - ['Ansökningsdatum', 'appl_date'], - ['Beslutsdatum', 'dec_date'], - //['Kommun', 'Municipality'], - //['Län', 'County'], - ], - legend: { zoomLevel: 4 }, - style: [0, .1, .5, .5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 5].map(function(width, z) { - return new Style({ - zIndex: 22, - fill: new Fill({ - color: [247, 170, 67, Math.max((.2-1)/8 * z + 1, 0)], - }), - stroke: width === 0 ? undefined : new Stroke({ - width: width, - color: [151, 173, 23, 1], - }), - }); - }), - }, - 'mrr.appl_ec': { - popoverTitle: 'Bearbetningskoncession \u2013 ansökt', - popover: [ - ['Namn', 'name'], - ['Koncessionsmineral', 'mineral'], - ['Sökande', 'owners'], - ['Areal', 'geom_area', { fn: 'area' }], - ['Ansökningsdatum', 'appl_date'], - ['Diarienummer', 'diarynr', { classes: ['feature-attr-dnr'] }], - //['Kommun', 'Municipality'], - //['Län', 'County'], - ], - legend: { zoomLevel: 4 }, - style: [0, .1, .5, .5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 5].map(function(width, z) { - return new Style({ - zIndex: 25, - fill: new Fill({ - color: [247, 170, 67, Math.max((.2-1)/8 * z + 1, 0)], - }), - stroke: width === 0 ? undefined : new Stroke({ - width: width, - color: [197, 14, 31, 1], - lineDash: width >= 1.5 ? [2 * width] : undefined, - }), - }); - }), - }, - 'mrr.appr_met': { - popoverTitle: 'Undersökningstillstånd, metaller och industrimineral \u2013 beviljad', - popover: [ - ['Namn', 'name'], - ['Koncessionsmineral', 'mineral'], - ['Ägare', 'owners'], - ['Tillståndsid', 'licenceid', { classes: ['feature-attr-mrr-license-id'] }], - ['Areal', 'geom_area', { fn: 'area' }], - ['Giltig från', 'validfrom'], - ['Giltig till', 'validto'], - ['Diarienummer', 'diarynr', { classes: ['feature-attr-dnr'] }], - ['Ansökningsdatum', 'appl_date'], - ['Beslutsdatum', 'dec_date'], - //['Kommun', 'Municipality'], - //['Län', 'County'], - ], - legend: { zoomLevel: 4 }, - style: [0, .1, .5, .5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 5].map(function(width, z) { - return new Style({ - zIndex: 24, - fill: new Fill({ - color: [0, 0, 0, Math.max((.2-.4)/4 * z + .4, 0)], - }), - stroke: width === 0 ? undefined : new Stroke({ - width: width, - color: [151, 173, 23, 1], - }), - }); - }), - }, - 'mrr.appl_met': { - popoverTitle: 'Undersökningstillstånd, metaller och industrimineral \u2013 ansökt', - popover: [ - ['Namn', 'name'], - ['Koncessionsmineral', 'mineral'], - ['Sökande', 'owners'], - ['Areal', 'geom_area', { fn: 'area' }], - ['Ansökningsdatum', 'appl_date'], - ['Diarienummer', 'diarynr', { classes: ['feature-attr-dnr'] }], - //['Kommun', 'Municipality'], - //['Län', 'County'], - ], - legend: { zoomLevel: 4 }, - style: [0, .1, .5, .5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 5].map(function(width, z) { - return new Style({ - zIndex: 26, - fill: new Fill({ - color: [0, 0, 0, Math.max((.2-.4)/4 * z + .4, 0)], - }), - stroke: width === 0 ? undefined : new Stroke({ - width: width, - color: [197, 14, 31, 1], - lineDash: width >= 1.5 ? [2 * width] : undefined, - }), - }); - }), - }, - 'mrr.appr_ogd': { - popoverTitle: 'Undersökningstillstånd, olja, gas och diamant \u2013 beviljad', - popover: [ - ['Namn', 'name'], - ['Koncessionsmineral', 'mineral'], - ['Ägare', 'owners'], - ['Tillståndsid', 'licenceid', { classes: ['feature-attr-mrr-license-id'] }], - ['Areal', 'geom_area', { fn: 'area' }], - ['Giltig från', 'validfrom'], - ['Giltig till', 'validto'], - ['Diarienummer', 'diarynr', { classes: ['feature-attr-dnr'] }], - ['Ansökningsdatum', 'appl_date'], - ['Beslutsdatum', 'dec_date'], - //['Kommun', 'Municipality'], - //['Län', 'County'], - ], - legend: { zoomLevel: 4 }, - style: [0, .1, .5, .5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 5].map(function(width, z) { - return new Style({ - zIndex: 24, - fill: new Fill({ - color: [30, 55, 87, Math.max((.2-.4)/4 * z + .4, 0)], - }), - stroke: width === 0 ? undefined : new Stroke({ - width: width, - color: [151, 173, 23, 1], - }), - }); - }), - }, - 'mrr.appl_ogd': { - popoverTitle: 'Undersökningstillstånd, olja, gas och diamant \u2013 ansökt', - popover: [ - ['Namn', 'name'], - ['Koncessionsmineral', 'mineral'], - ['Sökande', 'owners'], - ['Areal', 'geom_area', { fn: 'area' }], - ['Ansökningsdatum', 'appl_date'], - ['Diarienummer', 'diarynr', { classes: ['feature-attr-dnr'] }], - //['Kommun', 'Municipality'], - //['Län', 'County'], - ], - legend: { zoomLevel: 4 }, - style: [0, .1, .5, .5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 5].map(function(width, z) { - return new Style({ - zIndex: 26, - fill: new Fill({ - color: [30, 55, 87, Math.max((.2-.4)/4 * z + .4, 0)], - }), - stroke: width === 0 ? undefined : new Stroke({ - width: width, - color: [197, 14, 31, 1], - lineDash: width >= 1.5 ? [2 * width] : undefined, - }), - }); - }), - }, - 'mrr.appr_dl': { - popoverTitle: 'Markanvisning till koncession', - popover: [ - ['Namn', 'name'], - ['Tillhörande bearbetnings\u00ADkoncession(er)', 'conc_name'], - ['Tillståndsid', 'licenceid', { classes: ['feature-attr-mrr-license-id'] }], - ['Areal', 'geom_area', { fn: 'area' }], - ['Diarienummer', 'diarynr', { classes: ['feature-attr-dnr'] }], - ['Ansökningsdatum', 'appl_date'], - ['Beslutsdatum', 'dec_date'], - //['Kommun', 'Municipality'], - //['Län', 'County'], - ], - legend: { zoomLevel: 4 }, - style: [0, .1, .5, .5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 5].map(function(width, z) { - return new Style({ - zIndex: 20, - fill: new Fill({ - color: [228, 53, 45, Math.max((.2-1)/6 * z + 1, 0)], - }), - stroke: width === 0 ? undefined : new Stroke({ - width: width, - color: [151, 173, 23, 1], - }), - }); - }), - }, - - 'svk.ledningar': { - popoverTitle: 'Kraftledning (befintlig)', - popover: [ - ['Förläggning', 'Placement'], - ['Spänning', 'Voltage', { unit: 'kV' }], - ['Ledlängd', 'geom_length', { fn: 'length' }], - ], - legend: { zoomLevel: 5, type: 'linestring', reuse_canvas: true }, - style: [1, 1.5, 2, 2, 2, 2, 3, 4, 5, 6, 8, 10].map(function(width) { - return new Style({ - zIndex: 52, - stroke: new Stroke({ - color: 'black', - width: width, - }), - }); - }), - }, - 'svk.stolpar': { - legend: { zoomLevel: 5, type: 'point' }, - style: [undefined, undefined, undefined, undefined, undefined] - .concat([3, 4, 5, 6, 8, 10, 15].map(function(radius) { - return new Style({ - zIndex: 51, - image: new CircleStyle({ - radius: radius, - fill: new Fill({ - color: 'black', - }), - }), - }); - })), - }, - 'svk.transmissionsnatsprojekt': { - popoverTitle: 'Transmissionsnätsprojekt', - popover: [ - ['Projektnamn', 'Name'], - ['Spänning', 'Voltage', { unit: 'kV' }], - ['Länk', 'Url', { fn: function(v) { - if (v == null | v === '') { - return; - } - const a = document.createElement('a'); - a.href = v; - a.target = '_blank'; - const i = document.createElement('i'); - i.classList.add('bi', 'bi-box-arrow-up-right'); - a.appendChild(i); - return a; - }}], - ], - legend: { zoomLevel: 5, type: 'linestring' }, - style: [1, 1.5, 2, 2, 2, 2, 3, 4, 5, 6, 8, 10].map(function(width) { - return new Style({ - zIndex: 53, - stroke: new Stroke({ - color: 'black', - width: width, - lineDash: [4 * width], - }), - }); - }), - }, - 'svk.stationer': { - legend: { zoomLevel: 3, type: 'point' }, - style: [3, 4, 5, 6, 7, 8.5, 10].map(function(radius) { - return new Style({ - zIndex: 50, - image: new RegularShape({ - radius: radius, - points: 4, - angle: Math.PI/4, - fill: new Fill({ - color: 'black', - }), - }), - }); - }) - .concat([.5, 1, 1.5, 2, 2].map(function(width) { - return new Style({ - zIndex: 50, - fill: new Fill({ - color: 'rgba(128, 128, 128, .7)', - }), - stroke: new Stroke({ - width: width, - color: 'rgb(0, 0, 0)', - }), - }); - })), - }, - - 'vbk.area_current': { - popoverTitle: 'Landbaserad projekteringsområde för vindkraft', - popover: [ - ['Projektnamn', 'Projektnamn'], - ['Områdes-ID', 'OmrID', { classes: ['feature-objid'] }], - ['Aktuella verk', 'AntalVerk'], - ['Antal ej koordinatsatta verk', 'AntalEjXY'], - ['Areal', 'geom_area', { fn: 'area' }], - ['Beräknad årsproduktion', 'Calprod', { unit: 'GWh' }], - ['Planerad byggstart', 'PlaneradByggstart'], - ['Planerat drifttagande', 'PlaneratDrift'], - ['Ändringsansökan pågår', 'AndringsansokanPagar'], - ['Under byggnation', 'UnderByggnation'], - ['Organisationsnamn', 'Organisationsnamn'], - ['Organisationsnummer', 'Organisationsnummer', { classes: ['feature-orgnr'] }], - //['Kommun', 'KOMNAMN'], - //['Län', 'LANSNAMN'], - ['Elområde', 'ElNamn'], - ['Senast uppdaterat', 'SenasteUppdaterat'], - ], - legend: { zoomLevel: 1 }, - style: [.5, 1, 1.5, 1.5, 2, 2, 2.5, 2.5, 3, 3.5, 4, 5].map(function(width, z) { - return new Style({ - zIndex: 10, - fill: new Fill({ - color: [168, 198, 223, Math.max((.2-1)/8 * z + 1, 0)], - }), - stroke: width === 0 ? undefined : new Stroke({ - width: width, - color: [56, 96, 130, 1], - }), - }); - }), - }, - 'vbk.area_notcurrent': { - popoverTitle: 'Landbaserad projekteringsområde för vindkraft \u2013 ej aktuell', - popover: [ - ['Projektnamn', 'Projektnamn'], - ['Områdes-ID', 'OmrID', { classes: ['feature-objid'] }], - ['Aktuella verk', 'AntalVerk'], - ['Antal ej koordinatsatta verk', 'AntalEjXY'], - ['Areal', 'geom_area', { fn: 'area' }], - ['Beräknad årsproduktion', 'Calprod', { unit: 'GWh' }], - ['Planerad byggstart', 'PlaneradByggstart'], - ['Planerat drifttagande', 'PlaneratDrift'], - ['Ändringsansökan pågår', 'AndringsansokanPagar'], - ['Organisationsnamn', 'Organisationsnamn'], - ['Organisationsnummer', 'Organisationsnummer', { classes: ['feature-orgnr'] }], - //['Kommun', 'KOMNAMN'], - //['Län', 'LANSNAMN'], - ['Elområde', 'ElNamn'], - ['Senast uppdaterat', 'SenasteUppdaterat'], - ], - legend: { zoomLevel: 1 }, - style: [.5, 1, 1.5, 1.5, 2, 2, 2.5, 2.5, 3, 3.5, 4, 5].map(function(width, z) { - return new Style({ - zIndex: 10, - fill: new Fill({ - color: [222, 163, 199, Math.max((.2-1)/8 * z + 1, 0)], - }), - stroke: width === 0 ? undefined : new Stroke({ - width: width, - color: [148, 55, 112, 1], - lineDash: width >= 1.5 ? [2 * width] : undefined, - }), - }); - }), - }, - 'vbk.offshore_completed': { - popoverTitle: 'Havsbaserad vindkraft \u2013 tillståndsansökan uppförd', - popover: [ - ['Projektnamn', 'Projektnamn'], - ['Områdes-ID', 'OmrID', { classes: ['feature-objid'] }], - ['Verksamhetsutövare', 'Organisationsnamn'], - ['Organisationsnummer', 'Organisationsnummer', { classes: ['feature-orgnr'] }], - ['Projektstatus', 'Projektstatus'], - ['Diarienummer', 'Diarienummer'], - ['Areal', 'geom_area', { fn: 'area' }], - ['Samrådsunderlag inlämnat', 'SamradsunderlagInlamnat'], - ['Tillståndsansökan inlämnad', 'AnsokanInlamnat'], - ['Tillståndsansökan beviljad', 'AnsokanBeviljad'], - ['Överklagad', 'AnsokanOverklagad'], - ['Natura2000 ansökan', 'Natura2000_Ansokan'], - ['Natura2000 beslutsdatum', 'Natura2000_Beslutdatum'], - ['Parken uppförd', 'Uppfort'], - ['Beviljat antal verk', 'BeviljatAntalVerk'], - ['Uppfört antal verk', 'UppfortAntalVerk'], - ['Beviljad maxhöjd', 'BeviljadMaxhojd', { unit: 'm' }], - ['Installerad effekt', 'InstalleradEffekt', { unit: 'MW' }], - ['Beräknad årsproduktion', 'Calprod', { unit: 'GWh' }], - ['Elområde', 'ElNamn'], - ['Senast uppdaterat', 'SenasteUppdaterat'], - ], - legend: { zoomLevel: 1 }, - style: [.5, 1, 1.5, 1.5, 2, 2, 2.5, 2.5, 3, 3.5, 4, 5].map(function(width, z) { - return new Style({ - zIndex: 17, - fill: new Fill({ - color: [38, 107, 29, .5], - }), - stroke: width === 0 ? undefined : new Stroke({ - width: width, - color: [38, 107, 29, 1], - }), - }); - }), - }, - 'vbk.offshore_approved': { - popoverTitle: 'Havsbaserad vindkraft \u2013 tillståndsansökan beviljad', - popover: [ - ['Projektnamn', 'Projektnamn'], - ['Områdes-ID', 'OmrID', { classes: ['feature-objid'] }], - ['Verksamhetsutövare', 'Organisationsnamn'], - ['Organisationsnummer', 'Organisationsnummer', { classes: ['feature-orgnr'] }], - ['Projektstatus', 'Projektstatus'], - ['Diarienummer', 'Diarienummer'], - ['Ändringsansökan pågår', 'AndringsansokanPagar'], - ['Areal', 'geom_area', { fn: 'area' }], - ['Samrådsunderlag inlämnat', 'SamradsunderlagInlamnat'], - ['Tillståndsansökan inlämnad', 'AnsokanInlamnat'], - ['Tillståndsansökan återkallad', 'AnsokanAterkallad'], - ['Tillståndsansökan beviljad', 'AnsokanBeviljad'], - ['Natura2000 ansökan', 'Natura2000_Ansokan'], - ['Natura2000 beslutsdatum', 'Natura2000_Beslutdatum'], - ['Under byggnation', 'UnderByggnation'], - ['Planerat antal verk (min)', 'PlaneratAntalVerkMin'], - ['Planerat antal verk (max)', 'PlaneratAntalVerkMax'], - ['Panerad totalhöjd (min)', 'PlaneradHojdMin', { unit: 'm' }], - ['Panerad totalhöjd (max)', 'PlaneradHojdMax', { unit: 'm' }], - ['Planerad årsproduktion (min)', 'PlaneradProduktionMin', { unit: 'GWh' }], - ['Planerad årsproduktion (max)', 'PlaneradProduktionMax', { unit: 'GWh' }], - ['Planerad byggstart', 'PlaneradByggstart'], - ['Planerat drifttagande', 'PlaneratDrift'], - ['Beviljat antal verk', 'BeviljatAntalVerk'], - ['Beviljad maxhöjd', 'BeviljadMaxhojd', { unit: 'm' }], - ['Elområde', 'ElNamn'], - ['Senast uppdaterat', 'SenasteUppdaterat'], - ], - legend: { zoomLevel: 1 }, - style: [.5, 1, 1.5, 1.5, 2, 2, 2.5, 2.5, 3, 3.5, 4, 5].map(function(width, z) { - return new Style({ - zIndex: 16, - fill: new Fill({ - color: [56, 160, 44, .5], - }), - stroke: width === 0 ? undefined : new Stroke({ - width: width, - color: [56, 160, 44, 1], - }), - }); - }), - }, - 'vbk.offshore_amended': { - popoverTitle: 'Havsbaserad vindkraft \u2013 ändringsansökan', - popover: [ - ['Projektnamn', 'Projektnamn'], - ['Områdes-ID', 'OmrID', { classes: ['feature-objid'] }], - ['Verksamhetsutövare', 'Organisationsnamn'], - ['Organisationsnummer', 'Organisationsnummer', { classes: ['feature-orgnr'] }], - ['Projektstatus', 'Projektstatus'], - ['Diarienummer', 'Diarienummer'], - //['Ändringsansökan pågår', 'AndringsansokanPagar'], - ['Areal', 'geom_area', { fn: 'area' }], - ['Samrådsunderlag inlämnat', 'SamradsunderlagInlamnat'], - ['Tillståndsansökan inlämnad', 'AnsokanInlamnat'], - //['Natura2000 ansökan', 'Natura2000_Ansokan'], - //['Natura2000 beslutsdatum', 'Natura2000_Beslutdatum'], - ['Planerat antal verk (min)', 'PlaneratAntalVerkMin'], - ['Planerat antal verk (max)', 'PlaneratAntalVerkMax'], - ['Panerad totalhöjd (min)', 'PlaneradHojdMin', { unit: 'm' }], - ['Panerad totalhöjd (max)', 'PlaneradHojdMax', { unit: 'm' }], - ['Planerad årsproduktion (min)', 'PlaneradProduktionMin', { unit: 'GWh' }], - ['Planerad årsproduktion (max)', 'PlaneradProduktionMax', { unit: 'GWh' }], - ['Planerad byggstart', 'PlaneradByggstart'], - ['Planerat drifttagande', 'PlaneratDrift'], - ['Elområde', 'ElNamn'], - ['Senast uppdaterat', 'SenasteUppdaterat'], - ], - legend: { zoomLevel: 2 }, - style: [4, 8, 16, 16, 32, 32, 64, 64, 64, 128, 128, 128].map(function(width, z) { - const patternCanvas = document.createElement('canvas'); - const patternContext = patternCanvas.getContext('2d'); - const w = z < 4 ? .5 : z <= 5 ? 1.5 : 4; - patternCanvas.width = width/2; - patternCanvas.height = patternCanvas.width; - patternContext.fillStyle = 'rgba(247, 105, 162, 1)'; - patternContext.beginPath(); - patternContext.arc(.75*patternCanvas.width, .75*patternCanvas.height, 1.5*w, 0, 2*Math.PI, true) - patternContext.fill(); - - const canvas = document.createElement('canvas'); - const context = canvas.getContext('2d'); - return new Style({ - zIndex: 17, - fill: new Fill({ - color: context.createPattern(patternCanvas, 'repeat'), - }), - stroke: width === 0 ? undefined : new Stroke({ - width: 2*w, - color: [247, 105, 162, 1], - lineDash: [8 * w], - }), - }); - }), - }, - 'vbk.offshore_rejected': { - popoverTitle: 'Havsbaserad vindkraft \u2013 tillståndsansökan avslagen', - popover: [ - ['Projektnamn', 'Projektnamn'], - ['Områdes-ID', 'OmrID', { classes: ['feature-objid'] }], - ['Verksamhetsutövare', 'Organisationsnamn'], - ['Organisationsnummer', 'Organisationsnummer', { classes: ['feature-orgnr'] }], - ['Projektstatus', 'Projektstatus'], - ['Diarienummer', 'Diarienummer'], - ['Areal', 'geom_area', { fn: 'area' }], - ['Samrådsunderlag inlämnat', 'SamradsunderlagInlamnat'], - ['Tillståndsansökan inlämnad', 'AnsokanInlamnat'], - ['Tillståndsansökan avslagen', 'AnsokanAvslagen'], - ['Natura2000 ansökan', 'Natura2000_Ansokan'], - ['Natura2000 beslutsdatum', 'Natura2000_Beslutdatum'], - ['Planerat antal verk (min)', 'PlaneratAntalVerkMin'], - ['Planerat antal verk (max)', 'PlaneratAntalVerkMax'], - ['Panerad totalhöjd (min)', 'PlaneradHojdMin', { unit: 'm' }], - ['Panerad totalhöjd (max)', 'PlaneradHojdMax', { unit: 'm' }], - ['Planerad årsproduktion (min)', 'PlaneradProduktionMin', { unit: 'GWh' }], - ['Planerad årsproduktion (max)', 'PlaneradProduktionMax', { unit: 'GWh' }], - ['Planerad byggstart', 'PlaneradByggstart'], - ['Planerat drifttagande', 'PlaneratDrift'], - ['Elområde', 'ElNamn'], - ['Senast uppdaterat', 'SenasteUppdaterat'], - ], - legend: { zoomLevel: 1 }, - style: [.5, 1, 1.5, 1.5, 2, 2, 2.5, 2.5, 3, 3.5, 4, 5].map(function(width, z) { - return new Style({ - zIndex: 11, - fill: new Fill({ - color: [227, 26, 28, .5], - }), - stroke: width === 0 ? undefined : new Stroke({ - width: width, - color: [227, 26, 28, 1], - }), - }); - }), - }, - 'vbk.offshore_appealed': { - popoverTitle: 'Havsbaserad vindkraft \u2013 överklagad', - popover: [ - ['Projektnamn', 'Projektnamn'], - ['Områdes-ID', 'OmrID', { classes: ['feature-objid'] }], - ['Verksamhetsutövare', 'Organisationsnamn'], - ['Organisationsnummer', 'Organisationsnummer', { classes: ['feature-orgnr'] }], - ['Projektstatus', 'Projektstatus'], - ['Diarienummer', 'Diarienummer'], - ['Areal', 'geom_area', { fn: 'area' }], - ['Samrådsunderlag inlämnat', 'SamradsunderlagInlamnat'], - ['Tillståndsansökan inlämnad', 'AnsokanInlamnat'], - ['Tillståndsansökan beviljad', 'AnsokanBeviljad'], - ['Överklagad', 'AnsokanOverklagad'], - ['Natura2000 ansökan', 'Natura2000_Ansokan'], - ['Natura2000 beslutsdatum', 'Natura2000_Beslutdatum'], - ['Planerat antal verk (min)', 'PlaneratAntalVerkMin'], - ['Planerat antal verk (max)', 'PlaneratAntalVerkMax'], - ['Panerad totalhöjd (min)', 'PlaneradHojdMin', { unit: 'm' }], - ['Panerad totalhöjd (max)', 'PlaneradHojdMax', { unit: 'm' }], - ['Planerad årsproduktion (min)', 'PlaneradProduktionMin', { unit: 'GWh' }], - ['Planerad årsproduktion (max)', 'PlaneradProduktionMax', { unit: 'GWh' }], - ['Planerad byggstart', 'PlaneradByggstart'], - ['Planerat drifttagande', 'PlaneratDrift'], - ['Beviljat antal verk', 'BeviljatAntalVerk'], - ['Beviljad maxhöjd', 'BeviljadMaxhojd', { unit: 'm' }], - ['Elområde', 'ElNamn'], - ['Senast uppdaterat', 'SenasteUppdaterat'], - ], - legend: { zoomLevel: 1 }, - style: [.5, 1, 1.5, 1.5, 2, 2, 2.5, 2.5, 3, 3.5, 4, 5].map(function(width, z) { - return new Style({ - zIndex: 15, - fill: new Fill({ - color: [177, 88, 40, .5], - }), - stroke: width === 0 ? undefined : new Stroke({ - width: width, - color: [177, 88, 40, 1], - }), - }); - }), - }, - 'vbk.offshore_applied': { - popoverTitle: 'Havsbaserad vindkraft \u2013 tillståndsansökan inlämnad', - popover: [ - ['Projektnamn', 'Projektnamn'], - ['Områdes-ID', 'OmrID', { classes: ['feature-objid'] }], - ['Verksamhetsutövare', 'Organisationsnamn'], - ['Organisationsnummer', 'Organisationsnummer', { classes: ['feature-orgnr'] }], - ['Projektstatus', 'Projektstatus'], - ['Diarienummer', 'Diarienummer'], - ['Areal', 'geom_area', { fn: 'area' }], - ['Samrådsunderlag inlämnat', 'SamradsunderlagInlamnat'], - ['Tillståndsansökan inlämnad', 'AnsokanInlamnat'], - ['Natura2000 ansökan', 'Natura2000_Ansokan'], - ['Natura2000 beslutsdatum', 'Natura2000_Beslutdatum'], - ['Planerat antal verk (min)', 'PlaneratAntalVerkMin'], - ['Planerat antal verk (max)', 'PlaneratAntalVerkMax'], - ['Panerad totalhöjd (min)', 'PlaneradHojdMin', { unit: 'm' }], - ['Panerad totalhöjd (max)', 'PlaneradHojdMax', { unit: 'm' }], - ['Planerad årsproduktion (min)', 'PlaneradProduktionMin', { unit: 'GWh' }], - ['Planerad årsproduktion (max)', 'PlaneradProduktionMax', { unit: 'GWh' }], - ['Planerad byggstart', 'PlaneradByggstart'], - ['Planerat drifttagande', 'PlaneratDrift'], - ['Elområde', 'ElNamn'], - ['Senast uppdaterat', 'SenasteUppdaterat'], - ], - legend: { zoomLevel: 1 }, - style: [.5, 1, 1.5, 1.5, 2, 2, 2.5, 2.5, 3, 3.5, 4, 5].map(function(width, z) { - return new Style({ - zIndex: 14, - fill: new Fill({ - color: [255, 127, 0, .5], - }), - stroke: width === 0 ? undefined : new Stroke({ - width: width, - color: [255, 128, 0, 1], - }), - }); - }), - }, - 'vbk.offshore_consultation': { - popoverTitle: 'Havsbaserad vindkraft \u2013 samråd inför tillståndsansökan', - popover: [ - ['Projektnamn', 'Projektnamn'], - ['Områdes-ID', 'OmrID', { classes: ['feature-objid'] }], - ['Verksamhetsutövare', 'Organisationsnamn'], - ['Organisationsnummer', 'Organisationsnummer', { classes: ['feature-orgnr'] }], - ['Projektstatus', 'Projektstatus'], - ['Diarienummer', 'Diarienummer'], - ['Areal', 'geom_area', { fn: 'area' }], - ['Samrådsunderlag inlämnat', 'SamradsunderlagInlamnat'], - ['Natura2000 ansökan', 'Natura2000_Ansokan'], - ['Natura2000 beslutsdatum', 'Natura2000_Beslutdatum'], - ['Planerat antal verk (min)', 'PlaneratAntalVerkMin'], - ['Planerat antal verk (max)', 'PlaneratAntalVerkMax'], - ['Panerad totalhöjd (min)', 'PlaneradHojdMin', { unit: 'm' }], - ['Panerad totalhöjd (max)', 'PlaneradHojdMax', { unit: 'm' }], - ['Planerad årsproduktion (min)', 'PlaneradProduktionMin', { unit: 'GWh' }], - ['Planerad årsproduktion (max)', 'PlaneradProduktionMax', { unit: 'GWh' }], - ['Planerad byggstart', 'PlaneradByggstart'], - ['Planerat drifttagande', 'PlaneratDrift'], - ['Elområde', 'ElNamn'], - ['Senast uppdaterat', 'SenasteUppdaterat'], - ], - legend: { zoomLevel: 1 }, - style: [.5, 1, 1.5, 1.5, 2, 2, 2.5, 2.5, 3, 3.5, 4, 5].map(function(width, z) { - return new Style({ - zIndex: 13, - fill: new Fill({ - color: [254, 217, 118, .65], - }), - stroke: width === 0 ? undefined : new Stroke({ - width: width, - color: [254, 183, 82, 1], - }), - }); - }), - }, - 'vbk.offshore_investigation': { - popoverTitle: 'Havsbaserad vindkraft \u2013 inledande undersökningar', - popover: [ - ['Projektnamn', 'Projektnamn'], - ['Områdes-ID', 'OmrID', { classes: ['feature-objid'] }], - ['Verksamhetsutövare', 'Organisationsnamn'], - ['Organisationsnummer', 'Organisationsnummer', { classes: ['feature-orgnr'] }], - ['Projektstatus', 'Projektstatus'], - ['Diarienummer', 'Diarienummer'], - ['Areal', 'geom_area', { fn: 'area' }], - ['Natura2000 ansökan', 'Natura2000_Ansokan'], - ['Natura2000 beslutsdatum', 'Natura2000_Beslutdatum'], - ['Planerat antal verk (min)', 'PlaneratAntalVerkMin'], - ['Planerat antal verk (max)', 'PlaneratAntalVerkMax'], - ['Panerad totalhöjd (min)', 'PlaneradHojdMin', { unit: 'm' }], - ['Panerad totalhöjd (max)', 'PlaneradHojdMax', { unit: 'm' }], - ['Planerad årsproduktion (min)', 'PlaneradProduktionMin', { unit: 'GWh' }], - ['Planerad årsproduktion (max)', 'PlaneradProduktionMax', { unit: 'GWh' }], - ['Planerad byggstart', 'PlaneradByggstart'], - ['Planerat drifttagande', 'PlaneratDrift'], - ['Elområde', 'ElNamn'], - ['Senast uppdaterat', 'SenasteUppdaterat'], - ], - legend: { zoomLevel: 1 }, - style: [4, 8, 16, 16, 32, 32, 64, 64, 64, 128, 128, 128].map(function(width, z) { - const patternCanvas = document.createElement('canvas'); - const patternContext = patternCanvas.getContext('2d'); - const w = z < 4 ? .5 : z <= 5 ? 1.5 : 4; - patternCanvas.width = width*2; - patternCanvas.height = patternCanvas.width; - patternContext.fillStyle = 'transparent'; - patternContext.strokeStyle = 'rgba(68, 90, 166, 1)'; - patternContext.lineWidth = w; - patternContext.beginPath(); - patternContext.moveTo(0, patternCanvas.height); - patternContext.lineTo(patternCanvas.width, 0); - patternContext.stroke(); - patternContext.moveTo(-patternCanvas.width, patternCanvas.height); - patternContext.lineTo(patternCanvas.width, -patternCanvas.height); - patternContext.stroke(); - patternContext.moveTo(0, 2*patternCanvas.height); - patternContext.lineTo(2*patternCanvas.width, 0); - patternContext.stroke(); - - const canvas = document.createElement('canvas'); - const context = canvas.getContext('2d'); - return new Style({ - zIndex: 12, - fill: new Fill({ - color: context.createPattern(patternCanvas, 'repeat'), - }), - stroke: width === 0 ? undefined : new Stroke({ - width: 2*w, - color: [68, 90, 166, 1], - lineDash: [8 * w], - }), - }); - }), - }, - 'vbk.offshore_revoked': { - popoverTitle: 'Havsbaserad vindkraft \u2013 inte aktuell eller återkallad', - popover: [ - ['Projektnamn', 'Projektnamn'], - ['Områdes-ID', 'OmrID', { classes: ['feature-objid'] }], - ['Verksamhetsutövare', 'Organisationsnamn'], - ['Organisationsnummer', 'Organisationsnummer', { classes: ['feature-orgnr'] }], - ['Projektstatus', 'Projektstatus'], - ['Diarienummer', 'Diarienummer'], - ['Areal', 'geom_area', { fn: 'area' }], - ['Samrådsunderlag inlämnat', 'SamradsunderlagInlamnat'], - ['Tillståndsansökan inlämnad', 'AnsokanInlamnat'], - ['Tillståndsansökan återkallad', 'AnsokanAterkallad'], - ['Tillståndsansökan beviljad', 'AnsokanBeviljad'], - ['Överklagad', 'AnsokanOverklagad'], - ['Natura2000 ansökan', 'Natura2000_Ansokan'], - ['Natura2000 beslutsdatum', 'Natura2000_Beslutdatum'], - ['Planerat antal verk (min)', 'PlaneratAntalVerkMin'], - ['Planerat antal verk (max)', 'PlaneratAntalVerkMax'], - ['Panerad totalhöjd (min)', 'PlaneradHojdMin', { unit: 'm' }], - ['Panerad totalhöjd (max)', 'PlaneradHojdMax', { unit: 'm' }], - ['Planerad årsproduktion (min)', 'PlaneradProduktionMin', { unit: 'GWh' }], - ['Planerad årsproduktion (max)', 'PlaneradProduktionMax', { unit: 'GWh' }], - ['Planerad byggstart', 'PlaneradByggstart'], - ['Planerat drifttagande', 'PlaneratDrift'], - ['Beviljat antal verk', 'BeviljatAntalVerk'], - ['Beviljad maxhöjd', 'BeviljadMaxhojd', { unit: 'm' }], - ['Elområde', 'ElNamn'], - ['Senast uppdaterat', 'SenasteUppdaterat'], - ], - legend: { zoomLevel: 1 }, - style: [.5, 1, 1.5, 1.5, 2, 2, 2.5, 2.5, 3, 3.5, 4, 5].map(function(width, z) { - return new Style({ - zIndex: 10, - fill: new Fill({ - color: [105, 61, 154, .5], - }), - stroke: width === 0 ? undefined : new Stroke({ - width: width, - color: [105, 62, 153, 1], - }), - }); - }), - }, - 'vbk.station_completed': { - popoverTitle: 'Landbaserad vindkraftverk \u2013 uppfört', - popover: [ - ['Verk-ID', 'VerkID', { classes: ['feature-objid'] }], - ['Områdes-ID', 'OmrID', { classes: ['feature-objid'] }], - ['Projektnamn', 'Projektnamn'], - ['Status', 'Status'], - ['Handlingstyp', 'Handlingstyp'], - ['Uppförandedatum', 'Uppfort'], - ['Miljöbalken tillstånd tidsbegränsning', 'MB_Tillstand'], - ['Totalhöjd', 'Totalhojd', { unit: 'm' }], - ['Navhöjd', 'Navhojd', { unit: 'm' }], - ['Rotordiameter', 'Rotordiameter', { unit: 'm' }], - ['Maxeffekt', 'Maxeffekt', { unit: 'MW' }], - ['Beräknad årsproduktion', 'Calprod', { unit: 'GWh' }], - ['Fabrikat', 'Fabrikat'], - ['Modell', 'Modell'], - ['Organisationsnamn', 'Organisationsnamn'], - ['Organisationsnummer', 'Organisationsnummer', { classes: ['feature-orgnr'] }], - ['Placering', 'Placering'], - //['Kommun', 'KOMNAMN'], - //['Län', 'LANSNAMN'], - ['Elområde', 'ElNamn'], - ['Datum för senaste uppdatering av verk', 'SenasteUppdaterat'], - ], - legend: { zoomLevel: 7, type: 'point' }, - style: [undefined, undefined, undefined, undefined, .125, .125, .25, .5, 1, 2, 4, 8].map(function(scale) { - return scale === undefined ? undefined : new Style({ - zIndex: 99, - image: new Icon({ - src: '/assets/icons/wind-turbine-completed.svg', - declutter: 'none', - scale: scale, - }), - }); - }), - }, - 'vbk.station_processed': { - popoverTitle: 'Landbaserad vindkraftverk \u2013 handlagt', - popover: [ - ['Verk-ID', 'VerkID', { classes: ['feature-objid'] }], - ['Områdes-ID', 'OmrID', { classes: ['feature-objid'] }], - ['Projektnamn', 'Projektnamn'], - ['Status', 'Status'], - ['Handlingstyp', 'Handlingstyp'], - ['Totalhöjd', 'Totalhojd', { unit: 'm' }], - ['Navhöjd', 'Navhojd', { unit: 'm' }], - ['Rotordiameter', 'Rotordiameter', { unit: 'm' }], - ['Maxeffekt', 'Maxeffekt', { unit: 'MW' }], - ['Beräknad årsproduktion', 'Calprod', { unit: 'GWh' }], - ['Fabrikat', 'Fabrikat'], - ['Modell', 'Modell'], - ['Organisationsnamn', 'Organisationsnamn'], - ['Organisationsnummer', 'Organisationsnummer', { classes: ['feature-orgnr'] }], - ['Placering', 'Placering'], - //['Kommun', 'KOMNAMN'], - //['Län', 'LANSNAMN'], - ['Elområde', 'ElNamn'], - ['Datum för senaste uppdatering av verk', 'SenasteUppdaterat'], - ], - legend: { zoomLevel: 7, type: 'point' }, - style: [undefined, undefined, undefined, undefined, .125, .125, .25, .5, 1, 2, 4, 8].map(function(scale) { - return scale === undefined ? undefined : new Style({ - zIndex: 99, - image: new Icon({ - src: '/assets/icons/wind-turbine-processed.svg', - declutter: 'none', - scale: scale, - }), - }); - }), - }, - 'vbk.station_approved': { - popoverTitle: 'Landbaserad vindkraftverk \u2013 beviljat', - popover: [ - ['Verk-ID', 'VerkID', { classes: ['feature-objid'] }], - ['Områdes-ID', 'OmrID', { classes: ['feature-objid'] }], - ['Projektnamn', 'Projektnamn'], - ['Status', 'Status'], - ['Handlingstyp', 'Handlingstyp'], - ['Miljöbalken tillstånd tidsbegränsning', 'MB_Tillstand'], - ['Totalhöjd', 'Totalhojd', { unit: 'm' }], - ['Navhöjd', 'Navhojd', { unit: 'm' }], - ['Rotordiameter', 'Rotordiameter', { unit: 'm' }], - ['Maxeffekt', 'Maxeffekt', { unit: 'MW' }], - ['Beräknad årsproduktion', 'Calprod', { unit: 'GWh' }], - ['Fabrikat', 'Fabrikat'], - ['Modell', 'Modell'], - ['Organisationsnamn', 'Organisationsnamn'], - ['Organisationsnummer', 'Organisationsnummer', { classes: ['feature-orgnr'] }], - ['Placering', 'Placering'], - //['Kommun', 'KOMNAMN'], - //['Län', 'LANSNAMN'], - ['Elområde', 'ElNamn'], - ['Datum för senaste uppdatering av verk', 'SenasteUppdaterat'], - ], - legend: { zoomLevel: 7, type: 'point' }, - style: [undefined, undefined, undefined, undefined, .125, .125, .25, .5, 1, 2, 4, 8].map(function(scale) { - return scale === undefined ? undefined : new Style({ - zIndex: 99, - image: new Icon({ - src: '/assets/icons/wind-turbine-approved.svg', - declutter: 'none', - scale: scale, - }), - }); - }), - }, - 'vbk.station_revoked': { - popoverTitle: 'Landbaserad vindkraftverk \u2013 inte längre aktuell/återkallat', - popover: [ - ['Verk-ID', 'VerkID', { classes: ['feature-objid'] }], - ['Områdes-ID', 'OmrID', { classes: ['feature-objid'] }], - ['Projektnamn', 'Projektnamn'], - ['Status', 'Status'], - ['Handlingstyp', 'Handlingstyp'], - ['Miljöbalken tillstånd tidsbegränsning', 'MB_Tillstand'], - ['Totalhöjd', 'Totalhojd', { unit: 'm' }], - ['Navhöjd', 'Navhojd', { unit: 'm' }], - ['Rotordiameter', 'Rotordiameter', { unit: 'm' }], - ['Maxeffekt', 'Maxeffekt', { unit: 'MW' }], - ['Beräknad årsproduktion', 'Calprod', { unit: 'GWh' }], - ['Fabrikat', 'Fabrikat'], - ['Modell', 'Modell'], - ['Organisationsnamn', 'Organisationsnamn'], - ['Organisationsnummer', 'Organisationsnummer', { classes: ['feature-orgnr'] }], - ['Placering', 'Placering'], - //['Kommun', 'KOMNAMN'], - //['Län', 'LANSNAMN'], - ['Elområde', 'ElNamn'], - ['Datum för senaste uppdatering av verk', 'SenasteUppdaterat'], - ], - legend: { zoomLevel: 7, type: 'point' }, - style: [undefined, undefined, undefined, undefined, .125, .125, .25, .5, 1, 2, 4, 8].map(function(scale) { - return scale === undefined ? undefined : new Style({ - zIndex: 99, - image: new Icon({ - src: '/assets/icons/wind-turbine-revoked.svg', - declutter: 'none', - scale: scale, - }), - }); - }), - }, - 'vbk.station_rejected': { - popoverTitle: 'Landbaserad vindkraftverk \u2013 avslagit/nekat', - popover: [ - ['Verk-ID', 'VerkID', { classes: ['feature-objid'] }], - ['Områdes-ID', 'OmrID', { classes: ['feature-objid'] }], - ['Projektnamn', 'Projektnamn'], - ['Status', 'Status'], - ['Handlingstyp', 'Handlingstyp'], - ['Miljöbalken tillstånd tidsbegränsning', 'MB_Tillstand'], - ['Totalhöjd', 'Totalhojd', { unit: 'm' }], - ['Navhöjd', 'Navhojd', { unit: 'm' }], - ['Rotordiameter', 'Rotordiameter', { unit: 'm' }], - ['Maxeffekt', 'Maxeffekt', { unit: 'MW' }], - ['Beräknad årsproduktion', 'Calprod', { unit: 'GWh' }], - ['Fabrikat', 'Fabrikat'], - ['Modell', 'Modell'], - ['Organisationsnamn', 'Organisationsnamn'], - ['Organisationsnummer', 'Organisationsnummer', { classes: ['feature-orgnr'] }], - ['Placering', 'Placering'], - //['Kommun', 'KOMNAMN'], - //['Län', 'LANSNAMN'], - ['Elområde', 'ElNamn'], - ['Datum för senaste uppdatering av verk', 'SenasteUppdaterat'], - ], - legend: { zoomLevel: 7, type: 'point' }, - style: [undefined, undefined, undefined, undefined, .125, .125, .25, .5, 1, 2, 4, 8].map(function(scale) { - return scale === undefined ? undefined : new Style({ - zIndex: 99, - image: new Icon({ - src: '/assets/icons/wind-turbine-rejected.svg', - declutter: 'none', - scale: scale, - }), - }); - }), - }, - 'vbk.station_dismounted': { - popoverTitle: 'Landbaserad vindkraftverk \u2013 nedmonterat', - popover: [ - ['Verk-ID', 'VerkID', { classes: ['feature-objid'] }], - ['Områdes-ID', 'OmrID', { classes: ['feature-objid'] }], - ['Projektnamn', 'Projektnamn'], - ['Status', 'Status'], - ['Handlingstyp', 'Handlingstyp'], - ['Uppförandedatum', 'Uppfort'], - ['Totalhöjd', 'Totalhojd', { unit: 'm' }], - ['Navhöjd', 'Navhojd', { unit: 'm' }], - ['Rotordiameter', 'Rotordiameter', { unit: 'm' }], - ['Maxeffekt', 'Maxeffekt', { unit: 'MW' }], - ['Beräknad årsproduktion', 'Calprod', { unit: 'GWh' }], - ['Fabrikat', 'Fabrikat'], - ['Modell', 'Modell'], - ['Organisationsnamn', 'Organisationsnamn'], - ['Organisationsnummer', 'Organisationsnummer', { classes: ['feature-orgnr'] }], - ['Placering', 'Placering'], - //['Kommun', 'KOMNAMN'], - //['Län', 'LANSNAMN'], - ['Elområde', 'ElNamn'], - ['Datum för senaste uppdatering av verk', 'SenasteUppdaterat'], - ], - legend: { zoomLevel: 7, type: 'point' }, - style: [undefined, undefined, undefined, undefined, .125, .125, .25, .5, 1, 2, 4, 8].map(function(scale) { - return scale === undefined ? undefined : new Style({ - zIndex: 99, - image: new Icon({ - src: '/assets/icons/wind-turbine-dismounted.svg', - declutter: 'none', - scale: scale, - }), - }); - }), - }, - 'vbk.station_appealed': { - popoverTitle: 'Landbaserad vindkraftverk \u2013 överklagat', - popover: [ - ['Verk-ID', 'VerkID', { classes: ['feature-objid'] }], - ['Områdes-ID', 'OmrID', { classes: ['feature-objid'] }], - ['Projektnamn', 'Projektnamn'], - ['Status', 'Status'], - ['Handlingstyp', 'Handlingstyp'], - ['Totalhöjd', 'Totalhojd', { unit: 'm' }], - ['Navhöjd', 'Navhojd', { unit: 'm' }], - ['Rotordiameter', 'Rotordiameter', { unit: 'm' }], - ['Maxeffekt', 'Maxeffekt', { unit: 'MW' }], - ['Beräknad årsproduktion', 'Calprod', { unit: 'GWh' }], - ['Fabrikat', 'Fabrikat'], - ['Modell', 'Modell'], - ['Organisationsnamn', 'Organisationsnamn'], - ['Organisationsnummer', 'Organisationsnummer', { classes: ['feature-orgnr'] }], - ['Placering', 'Placering'], - //['Kommun', 'KOMNAMN'], - //['Län', 'LANSNAMN'], - ['Elområde', 'ElNamn'], - ['Datum för senaste uppdatering av verk', 'SenasteUppdaterat'], - ], - legend: { zoomLevel: 7, type: 'point' }, - style: [undefined, undefined, undefined, undefined, .125, .125, .25, .5, 1, 2, 4, 8].map(function(scale) { - return scale === undefined ? undefined : new Style({ - zIndex: 99, - image: new Icon({ - src: '/assets/icons/wind-turbine-appealed.svg', - declutter: 'none', - scale: scale, - }), - }); - }), - }, - - /* Documentation at - * https://www.skogsstyrelsen.se/globalassets/sjalvservice/karttjanster/geodatatjanster/produktbeskrivningar/utforda-avverkningar---produktbeskrivning.pdf - * */ - 'avverk.utford': { - popoverTitle: 'Utförd avverkning', - popover: [ - ['Ärendebeteckning', 'Beteckn', { classes: ['feature-objid'] }], - ['Registeringsår', 'ArendeAr'], - ['Skogstyp', 'Skogstyp'], - ['Areal anmält', 'AnmaldHa', { unit: 'ha' }], - ['Areal naturlig föryngring', 'NatforHa', { unit: 'ha', fn: (v) => v === 0 ? '' : v }], - //['Areal plantering', 'SkogsodlHa', { unit: 'ha', fn: (v) => v === 0 ? '' : v }], - ['Avverkningstyp', 'Avverktyp'], - ['Datum för avverkning', 'Avvdatum'], - ['Ursprung för datum för avverkning', 'KallaDatum'], - //['Ursprung för areal avverkning', 'KallaAreal'], - //['Kommun', 'Kommun'], - //['Län', 'Lan'], - ['Areal för ytan', 'geom_area', { fn: 'area' }], - ], - legend: { zoomLevel: 7 }, - style: [0, 0, 0, 0, 0, .5, .75, 1, 1, 1, 1, 1].map(function(width, z) { - return new Style({ - zIndex: 10, - fill: new Fill({ - color: [255, 102, 102, Math.max((.2-1)/8 * z + 1, 0)], - }), - stroke: width === 0 ? undefined : new Stroke({ - width: width, - color: [204, 0, 0, 1], - }), - }); - }), - }, - /* Documentation at - * https://www.skogsstyrelsen.se/globalassets/sjalvservice/karttjanster/geodatatjanster/produktbeskrivningar/yttre-granser-for-avverkningsanmalda-omraden---produktbeskrivning.pdf - * */ - 'avverk.anmald': { - popoverTitle: 'Avverkningsanmälansområde', - popover: [ - ['Ärendebeteckning', 'Beteckn', { classes: ['feature-objid'] }], - ['Inkom datum', 'Inkomdatum'], - ['Registeringsår', 'ArendeAr'], - //['Skogstyp', 'Skogstyp'], - ['Areal anmält', 'AnmaldHa', { unit: 'ha' }], - ['Areal naturlig föryngring', 'NatforHa', { unit: 'ha', fn: (v) => v === 0 ? '' : v }], - ['Areal plantering', 'SkogsodlHa', { unit: 'ha', fn: (v) => v === 0 ? '' : v }], - ['Avverkningssäsong', 'AvvSasong'], - //['Avverkningstyp', 'Avverktyp'], - //['Ändamål', 'Andamal'], - //['Kommun', 'Kommun'], - //['Län', 'Lan'], - ['Ärendestatus', 'ArendeStatus'], - ['Avverkad areal', 'AvvHa', { unit: 'ha' }], - ], - legend: { zoomLevel: 7 }, - style: [0, 0, 0, 0, 0, .5, .75, 1, 1, 1, 1, 1].map(function(width, z) { - return new Style({ - zIndex: 10, - fill: (width === undefined || width === 0) ? - new Fill({ color: [255, 102, 102, Math.max((.2-1)/8 * z + 1, 0)*.75] }) : - (function() { - const patternCanvas = document.createElement('canvas'); - const patternContext = patternCanvas.getContext('2d'); - const slope = 45 * Math.PI/180; - const spacing = z < 10 ? z*2 : 40; - const len = Math.hypot(1, slope); - const w = patternCanvas.width = Math.round(1/len + spacing) - const h = patternCanvas.height = Math.round(slope/len + spacing * slope); - - patternContext.fillStyle = 'rgba(255, 102, 102, .1)'; - patternContext.fillRect(0, 0, patternCanvas.width, patternCanvas.height); - patternContext.strokeStyle = 'rgba(204, 0, 0, 1)'; - patternContext.lineWidth = Math.max(1, width/2); - patternContext.beginPath(); - patternContext.moveTo(0, h); - patternContext.lineTo(w, 0); - patternContext.moveTo(-w, h); - patternContext.lineTo(w, -h); - patternContext.moveTo(0, 2*h); - patternContext.lineTo(2*w, 0); - patternContext.stroke(); - - const canvas = document.createElement('canvas'); - const context = canvas.getContext('2d'); - return new Fill({ color: context.createPattern(patternCanvas, 'repeat') }); - })(), - stroke: width === 0 ? undefined : new Stroke({ - width: width, - color: [204, 0, 0, 1], - lineDash: width >= 1.5 ? [2 * width] : undefined, - }), - }); - }), - }, - - 'skydd.tilltradesforbud': { - popoverTitle: 'Tillträdesförbud', - popover: [ - ['NVR-ID', 'NVRID', { classes: ['feature-objid'] }], - ['Föreskriftsområde', 'FORSKRNAMN'], - ['Namn', 'OBJEKTNAMN'], - ['Beslutsstatus', 'BESLSTAT'], - ['Föreskriftstyp', 'FORESKRTYP'], - ['Föreskriftssubtyp', 'FORESKRIFT'], - ['Från datum', 'FRANDATUM'], - ['Till datum', 'TILLDATUM'], - ['Beskrivning', 'BESKRIVN'], - ['Areal', 'geom_area', { fn: 'area' }], - ], - legend: { zoomLevel: 2 }, - style: [1, 1.5, 2, 3, 3.5, 4, 5, 5, 6, 7, 8, 10].map(function(width, z) { - return new Style({ - zIndex: 23, - fill: new Fill({ - /* transparent fill so clicking the inside of the polygon triggers a popover */ - /* XXX could also use a custom renderer but that doesn't seem to work */ - color: [0, 0, 0, 0], - }), - stroke: width === 0 ? undefined : new Stroke({ - width: width, - color: [255, 0, 0, 1], - }), - }); - }), - }, - 'skydd.nationalpark': { - popoverTitle: 'Nationalpark', - popover: [ - ['NVR-ID', 'NVRID', { classes: ['feature-objid'] }], - ['Namn', 'NAMN'], - ['Skyddstyp', 'SKYDDSTYP'], - ['Beslutsstatus', 'BESLSTATUS'], - ['Beslutsdatum (bildande)', 'URSBESLDAT'], - ['Ursprungligt gällandedatum', 'URSGALLDAT'], - ['Senaste gällandedatum', 'SENGALLDAT'], - ['Förvaltare', 'FORVALTARE'], - ['IUCN-kategori', 'IUCNKAT'], - ['Diarienummer', 'DIARIENR', { classes: ['feature-attr-dnr'] }], - ['Lagrum', 'LAGRUM'], - ['Beslutsmyndighet', 'BESLMYND'], - ['Areal', 'geom_area', { fn: 'area' }], - ['Areal land', 'LAND_HA', { unit: 'ha' }], - ['Areal vatten', 'VATTEN_HA', { unit: 'ha' }], - ['Skogsmarksareal', 'SKOG_HA', { unit: 'ha' }], - ], - legend: { zoomLevel: 1 }, - style: [8, 16, 32, 32, 64, 64, 128, 128, 128, 256, 256, 256].map(function(width, z) { - const patternCanvas = document.createElement('canvas'); - const patternContext = patternCanvas.getContext('2d'); - patternCanvas.width = width; - patternCanvas.height = patternCanvas.width; - patternContext.fillStyle = 'transparent'; - patternContext.strokeStyle = 'rgba(0, 55, 0, 1)'; - patternContext.lineWidth = z < 4 ? .5 : z <= 5 ? 1 : 2; - patternContext.beginPath(); - patternContext.moveTo(0, patternCanvas.height); - patternContext.lineTo(patternCanvas.width, 0); - patternContext.stroke(); - patternContext.moveTo(-patternCanvas.width, patternCanvas.height); - patternContext.lineTo(patternCanvas.width, -patternCanvas.height); - patternContext.stroke(); - patternContext.moveTo(0, 2*patternCanvas.height); - patternContext.lineTo(2*patternCanvas.width, 0); - patternContext.stroke(); - - const canvas = document.createElement('canvas'); - const context = canvas.getContext('2d'); - return new Style({ - zIndex: 22, - fill: new Fill({ - color: context.createPattern(patternCanvas, 'repeat'), - }), - stroke: width === 0 ? undefined : new Stroke({ - width: z < 2 ? 1 : z < 4 ? 2 : z <= 5 ? 4 : 8, - color: [0, 55, 0, 1], - }), - }); - }), - }, - 'skydd.naturreservat': { - popoverTitle: 'Naturreservat', - popover: [ - ['NVR-ID', 'NVRID', { classes: ['feature-objid'] }], - ['Namn', 'NAMN'], - ['Skyddstyp', 'SKYDDSTYP'], - ['Beslutsstatus', 'BESLSTATUS'], - ['Beslutsdatum (bildande)', 'URSBESLDAT'], - ['Ursprungligt gällandedatum', 'URSGALLDAT'], - ['Senaste gällandedatum', 'SENGALLDAT'], - ['Förvaltare', 'FORVALTARE'], - ['IUCN-kategori', 'IUCNKAT'], - ['Diarienummer', 'DIARIENR', { classes: ['feature-attr-dnr'] }], - ['Lagrum', 'LAGRUM'], - ['Beslutsmyndighet', 'BESLMYND'], - ['Areal', 'geom_area', { fn: 'area' }], - ['Areal land', 'LAND_HA', { unit: 'ha' }], - ['Areal vatten', 'VATTEN_HA', { unit: 'ha' }], - ['Skogsmarksareal', 'SKOG_HA', { unit: 'ha' }], - ], - legend: { zoomLevel: 1 }, - style: [8, 16, 32, 32, 64, 64, 128, 128, 128, 256, 256, 256].map(function(width, z) { - const patternCanvas = document.createElement('canvas'); - const patternContext = patternCanvas.getContext('2d'); - patternCanvas.width = width; - patternCanvas.height = patternCanvas.width; - patternContext.fillStyle = 'transparent'; - patternContext.strokeStyle = 'rgba(7, 181, 7, 1)'; - patternContext.lineWidth = z < 4 ? .5 : z <= 5 ? 1 : 2; - patternContext.beginPath(); - patternContext.moveTo(0, patternCanvas.height); - patternContext.lineTo(patternCanvas.width, 0); - patternContext.stroke(); - patternContext.moveTo(-patternCanvas.width, patternCanvas.height); - patternContext.lineTo(patternCanvas.width, -patternCanvas.height); - patternContext.stroke(); - patternContext.moveTo(0, 2*patternCanvas.height); - patternContext.lineTo(2*patternCanvas.width, 0); - patternContext.stroke(); - - const canvas = document.createElement('canvas'); - const context = canvas.getContext('2d'); - return new Style({ - zIndex: 21, - fill: new Fill({ - color: context.createPattern(patternCanvas, 'repeat'), - }), - stroke: width === 0 ? undefined : new Stroke({ - width: z < 2 ? 1 : z < 4 ? 2 : z <= 5 ? 4 : 8, - color: [7, 181, 7, 1], - }), - }); - }), - }, - 'skydd.naturreservat_kommunalt': { - popoverTitle: 'Kommunalt naturreservat', - popover: [ - ['NVR-ID', 'NVRID', { classes: ['feature-objid'] }], - ['Namn', 'NAMN'], - ['Skyddstyp', 'SKYDDSTYP'], - ['Beslutsstatus', 'BESLSTATUS'], - ['Beslutsdatum (bildande)', 'URSBESLDAT'], - ['Ursprungligt gällandedatum', 'URSGALLDAT'], - ['Senaste gällandedatum', 'SENGALLDAT'], - ['Förvaltare', 'FORVALTARE'], - ['IUCN-kategori', 'IUCNKAT'], - ['Diarienummer', 'DIARIENR', { classes: ['feature-attr-dnr'] }], - ['Lagrum', 'LAGRUM'], - ['Beslutsmyndighet', 'BESLMYND'], - ['Areal', 'geom_area', { fn: 'area' }], - ['Areal land', 'LAND_HA', { unit: 'ha' }], - ['Areal vatten', 'VATTEN_HA', { unit: 'ha' }], - ['Skogsmarksareal', 'SKOG_HA', { unit: 'ha' }], - ], - legend: { zoomLevel: 2 }, - style: [4, 8, 16, 16, 32, 32, 64, 64, 64, 128, 128, 128].map(function(width, z) { - const patternCanvas = document.createElement('canvas'); - const patternContext = patternCanvas.getContext('2d'); - patternCanvas.width = width; - patternCanvas.height = patternCanvas.width; - patternContext.fillStyle = 'transparent'; - patternContext.strokeStyle = 'rgba(7, 181, 7, 1)'; - patternContext.lineWidth = z < 4 ? .5 : z <= 5 ? 1 : 2; - patternContext.beginPath(); - patternContext.moveTo(0, 0); - patternContext.lineTo(patternCanvas.width, patternCanvas.height); - patternContext.stroke(); - patternContext.moveTo(0, -patternCanvas.height); - patternContext.lineTo(2*patternCanvas.width, patternCanvas.height); - patternContext.stroke(); - patternContext.moveTo(-patternCanvas.width, 0); - patternContext.lineTo(patternCanvas.width, 2*patternCanvas.height); - patternContext.stroke(); - - const canvas = document.createElement('canvas'); - const context = canvas.getContext('2d'); - return new Style({ - zIndex: 20, - fill: new Fill({ - color: context.createPattern(patternCanvas, 'repeat'), - }), - stroke: width === 0 ? undefined : new Stroke({ - width: z < 2 ? 1 : z < 4 ? 2 : z <= 5 ? 4 : 8, - color: [7, 181, 7, 1], - }), - }); - }), - }, - 'skydd.naturvardsomrade': { - popoverTitle: 'Naturvårdsområde', - popover: [ - ['NVR-ID', 'NVRID', { classes: ['feature-objid'] }], - ['Namn', 'NAMN'], - ['Skyddstyp', 'SKYDDSTYP'], - ['Beslutsstatus', 'BESLSTATUS'], - ['Beslutsdatum (bildande)', 'URSBESLDAT'], - ['Ursprungligt gällandedatum', 'URSGALLDAT'], - ['Senaste gällandedatum', 'SENGALLDAT'], - ['Förvaltare', 'FORVALTARE'], - ['IUCN-kategori', 'IUCNKAT'], - ['Diarienummer', 'DIARIENR', { classes: ['feature-attr-dnr'] }], - ['Lagrum', 'LAGRUM'], - ['Beslutsmyndighet', 'BESLMYND'], - ['Areal', 'geom_area', { fn: 'area' }], - ['Areal land', 'LAND_HA', { unit: 'ha' }], - ['Areal vatten', 'VATTEN_HA', { unit: 'ha' }], - ['Skogsmarksareal', 'SKOG_HA', { unit: 'ha' }], - ], - legend: { zoomLevel: 2 }, - style: [4, 8, 16, 16, 32, 32, 64, 64, 64, 128, 128, 128].map(function(width, z) { - const patternCanvas = document.createElement('canvas'); - const patternContext = patternCanvas.getContext('2d'); - patternCanvas.width = width; - patternCanvas.height = patternCanvas.width; - patternContext.fillStyle = 'transparent'; - patternContext.strokeStyle = 'rgba(176, 255, 176, 1)'; - patternContext.lineWidth = z < 4 ? .5 : z <= 5 ? 1 : 2; - patternContext.beginPath(); - patternContext.moveTo(0, patternCanvas.height); - patternContext.lineTo(patternCanvas.width, 0); - patternContext.stroke(); - patternContext.moveTo(-patternCanvas.width, patternCanvas.height); - patternContext.lineTo(patternCanvas.width, -patternCanvas.height); - patternContext.stroke(); - patternContext.moveTo(0, 2*patternCanvas.height); - patternContext.lineTo(2*patternCanvas.width, 0); - patternContext.stroke(); - - const canvas = document.createElement('canvas'); - const context = canvas.getContext('2d'); - return new Style({ - zIndex: 19, - fill: new Fill({ - color: context.createPattern(patternCanvas, 'repeat'), - }), - stroke: width === 0 ? undefined : new Stroke({ - width: z < 2 ? 1 : z < 4 ? 2 : z <= 5 ? 4 : 8, - color: [176, 255, 176, 1], - }), - }); - }), - }, - 'skydd.djur_och_vaxtskyddsomrade': { - popoverTitle: 'Djur- och växtskyddsområde', - popover: [ - ['NVR-ID', 'NVRID', { classes: ['feature-objid'] }], - ['Namn', 'NAMN'], - ['Skyddstyp', 'SKYDDSTYP'], - ['Beslutsstatus', 'BESLSTATUS'], - ['Beslutsdatum (bildande)', 'URSBESLDAT'], - ['Ursprungligt gällandedatum', 'URSGALLDAT'], - ['Senaste gällandedatum', 'SENGALLDAT'], - ['Förvaltare', 'FORVALTARE'], - ['IUCN-kategori', 'IUCNKAT'], - ['Diarienummer', 'DIARIENR', { classes: ['feature-attr-dnr'] }], - ['Lagrum', 'LAGRUM'], - ['Beslutsmyndighet', 'BESLMYND'], - ['Areal', 'geom_area', { fn: 'area' }], - ['Areal land', 'LAND_HA', { unit: 'ha' }], - ['Areal vatten', 'VATTEN_HA', { unit: 'ha' }], - ['Skogsmarksareal', 'SKOG_HA', { unit: 'ha' }], - ], - legend: { zoomLevel: 2 }, - style: [4, 8, 16, 16, 32, 32, 64, 64, 64, 128, 128, 128].map(function(width, z) { - const patternCanvas = document.createElement('canvas'); - const patternContext = patternCanvas.getContext('2d'); - patternCanvas.width = width; - patternCanvas.height = patternCanvas.width; - patternContext.fillStyle = 'transparent'; - patternContext.strokeStyle = 'rgba(255, 255, 0, 1)'; - patternContext.lineWidth = z < 4 ? .5 : z <= 5 ? 1 : 2; - patternContext.beginPath(); - patternContext.moveTo(0, patternCanvas.height); - patternContext.lineTo(patternCanvas.width, 0); - patternContext.stroke(); - patternContext.moveTo(-patternCanvas.width, patternCanvas.height); - patternContext.lineTo(patternCanvas.width, -patternCanvas.height); - patternContext.stroke(); - patternContext.moveTo(0, 2*patternCanvas.height); - patternContext.lineTo(2*patternCanvas.width, 0); - patternContext.stroke(); - - const canvas = document.createElement('canvas'); - const context = canvas.getContext('2d'); - return new Style({ - zIndex: 18, - fill: new Fill({ - color: context.createPattern(patternCanvas, 'repeat'), - }), - stroke: width === 0 ? undefined : new Stroke({ - width: z < 2 ? 1 : z < 4 ? 2 : z <= 5 ? 4 : 8, - color: [255, 255, 0, 1], - }), - }); - }), - }, - 'skydd.kulturreservat': { - popoverTitle: 'Kulturreservat', - popover: [ - ['NVR-ID', 'NVRID', { classes: ['feature-objid'] }], - ['Namn', 'NAMN'], - ['Skyddstyp', 'SKYDDSTYP'], - ['Beslutsstatus', 'BESLSTATUS'], - ['Beslutsdatum (bildande)', 'URSBESLDAT'], - ['Ursprungligt gällandedatum', 'URSGALLDAT'], - ['Senaste gällandedatum', 'SENGALLDAT'], - ['Förvaltare', 'FORVALTARE'], - ['IUCN-kategori', 'IUCNKAT'], - ['Diarienummer', 'DIARIENR', { classes: ['feature-attr-dnr'] }], - ['Lagrum', 'LAGRUM'], - ['Beslutsmyndighet', 'BESLMYND'], - ['Areal', 'geom_area', { fn: 'area' }], - ['Areal land', 'LAND_HA', { unit: 'ha' }], - ['Areal vatten', 'VATTEN_HA', { unit: 'ha' }], - ['Skogsmarksareal', 'SKOG_HA', { unit: 'ha' }], - ], - legend: { zoomLevel: 2 }, - style: [4, 8, 16, 16, 32, 32, 64, 64, 64, 128, 128, 128].map(function(width, z) { - const patternCanvas = document.createElement('canvas'); - const patternContext = patternCanvas.getContext('2d'); - patternCanvas.width = width; - patternCanvas.height = patternCanvas.width; - patternContext.fillStyle = 'transparent'; - patternContext.strokeStyle = 'rgba(154, 102, 255, 1)'; - patternContext.lineWidth = z < 4 ? .5 : z <= 5 ? 1 : 2; - patternContext.beginPath(); - patternContext.moveTo(0, patternCanvas.height); - patternContext.lineTo(patternCanvas.width, 0); - patternContext.stroke(); - patternContext.moveTo(-patternCanvas.width, patternCanvas.height); - patternContext.lineTo(patternCanvas.width, -patternCanvas.height); - patternContext.stroke(); - patternContext.moveTo(0, 2*patternCanvas.height); - patternContext.lineTo(2*patternCanvas.width, 0); - patternContext.stroke(); - - const canvas = document.createElement('canvas'); - const context = canvas.getContext('2d'); - return new Style({ - zIndex: 17, - fill: new Fill({ - color: context.createPattern(patternCanvas, 'repeat'), - }), - stroke: width === 0 ? undefined : new Stroke({ - width: z < 2 ? 1 : z < 4 ? 2 : z <= 5 ? 4 : 8, - color: [154, 102, 255, 1], - }), - }); - }), - }, - 'skydd.vattenskyddsomrade': { - popoverTitle: 'Vattenskyddsområden', - popover: [ - ['NVR-ID', 'NVRID', { classes: ['feature-objid'] }], - ['Namn', 'NAMN'], - ['Skyddstyp', 'SKYDDSTYP'], - ['Beslutsstatus', 'BESLSTATUS'], - ['Beslutsdatum (bildande)', 'URSBESLDAT'], - ['Ikraftträdandedatum föreskrifter', 'IKRAFTDATF'], - ['Beslutsmyndighet', 'BESLMYND'], - ['Tillsynsmyndighet', 'TILLSYNSMH'], - ['Prövningsmyndighet tillstånd', 'PROVNMHTIL'], - ['Prövningsmyndighet dispens', 'PROVNMHDIS'], - ['Diarienummer', 'DIARIENR', { classes: ['feature-attr-dnr'] }], - ['Lagrum', 'LAGRUM'], - ['Areal', 'geom_area', { fn: 'area' }], - ['Areal land', 'LAND_HA', { unit: 'ha' }], - ['Areal vatten', 'VATTEN_HA', { unit: 'ha' }], - ['Skogsmarksareal', 'SKOG_HA', { unit: 'ha' }], - ], - legend: { zoomLevel: 2 }, - style: [4, 8, 16, 16, 32, 32, 64, 64, 64, 128, 128, 128].map(function(width, z) { - const patternCanvas = document.createElement('canvas'); - const patternContext = patternCanvas.getContext('2d'); - patternCanvas.width = width; - patternCanvas.height = patternCanvas.width; - patternContext.fillStyle = 'transparent'; - patternContext.strokeStyle = 'rgba(0, 105, 212, 1)'; - patternContext.lineWidth = z < 4 ? .5 : z <= 5 ? 1 : 2; - patternContext.beginPath(); - patternContext.moveTo(0, patternCanvas.height); - patternContext.lineTo(patternCanvas.width, 0); - patternContext.stroke(); - patternContext.moveTo(-patternCanvas.width, patternCanvas.height); - patternContext.lineTo(patternCanvas.width, -patternCanvas.height); - patternContext.stroke(); - patternContext.moveTo(0, 2*patternCanvas.height); - patternContext.lineTo(2*patternCanvas.width, 0); - patternContext.stroke(); - - const canvas = document.createElement('canvas'); - const context = canvas.getContext('2d'); - return new Style({ - zIndex: 16, - fill: new Fill({ - color: context.createPattern(patternCanvas, 'repeat'), - }), - stroke: width === 0 ? undefined : new Stroke({ - width: z < 2 ? 1 : z < 4 ? 2 : z <= 5 ? 4 : 8, - color: [0, 105, 212, 1], - }), - }); - }), - }, - 'skydd.landskapsbildsskyddsomrade': { - popoverTitle: 'Landskapsbildsskyddsområde', - popover: [ - ['NVR-ID', 'NVRID', { classes: ['feature-objid'] }], - ['Namn', 'NAMN'], - ['Skyddstyp', 'SKYDDSTYP'], - ['Beslutsstatus', 'BESLSTATUS'], - ['Beslutsdatum (bildande)', 'URSBESLDAT'], - ['Ursprungligt gällandedatum', 'URSGALLDAT'], - ['Senaste gällandedatum', 'SENGALLDAT'], - ['Förvaltare', 'FORVALTARE'], - ['IUCN-kategori', 'IUCNKAT'], - ['Diarienummer', 'DIARIENR', { classes: ['feature-attr-dnr'] }], - ['Lagrum', 'LAGRUM'], - ['Beslutsmyndighet', 'BESLMYND'], - ['Areal', 'geom_area', { fn: 'area' }], - ['Areal land', 'LAND_HA', { unit: 'ha' }], - ['Areal vatten', 'VATTEN_HA', { unit: 'ha' }], - ['Skogsmarksareal', 'SKOG_HA', { unit: 'ha' }], - ], - legend: { zoomLevel: 2 }, - style: [4, 8, 16, 16, 32, 32, 64, 64, 64, 128, 128, 128].map(function(width, z) { - const patternCanvas = document.createElement('canvas'); - const patternContext = patternCanvas.getContext('2d'); - patternCanvas.width = width; - patternCanvas.height = patternCanvas.width; - patternContext.fillStyle = 'transparent'; - patternContext.strokeStyle = 'rgba(135, 110, 71, 1)'; - patternContext.lineWidth = z < 4 ? .5 : z <= 5 ? 1 : 2; - patternContext.beginPath(); - patternContext.moveTo(0, patternCanvas.height); - patternContext.lineTo(patternCanvas.width, 0); - patternContext.stroke(); - patternContext.moveTo(-patternCanvas.width, patternCanvas.height); - patternContext.lineTo(patternCanvas.width, -patternCanvas.height); - patternContext.stroke(); - patternContext.moveTo(0, 2*patternCanvas.height); - patternContext.lineTo(2*patternCanvas.width, 0); - patternContext.stroke(); - - const canvas = document.createElement('canvas'); - const context = canvas.getContext('2d'); - return new Style({ - zIndex: 15, - fill: new Fill({ - color: context.createPattern(patternCanvas, 'repeat'), - }), - stroke: width === 0 ? undefined : new Stroke({ - width: z < 2 ? 1 : z < 4 ? 2 : z <= 5 ? 4 : 8, - color: [134, 110, 71, 1], - }), - }); - }), - }, - 'skydd.skogligt_biotopskyddsomrade': { - popoverTitle: 'Biotopskydd i skogsmark', - popover: [ - ['Ärendebeteckning', 'Beteckn', { classes: ['feature-objid'] }], - ['Biotopkategori', 'Biotyp'], - ['Skogstyp', 'Naturtyp'], - ['Registeringsår', 'ArendeAr'], - ['Areal', 'geom_area', { fn: 'area' }], - ['Skogsmarksareal', 'AreaProd', { unit: 'ha' }], - ['Beslutsdatum', 'Datbeslut'], - ['Länk', 'Url', { fn: function(v) { - if (v == null | v === '') { - return; - } - const a = document.createElement('a'); - a.href = v; - a.target = '_blank'; - const i = document.createElement('i'); - i.classList.add('bi', 'bi-box-arrow-up-right'); - a.appendChild(i); - return a; - }}], - ], - legend: { zoomLevel: 2 }, - style: [4, 8, 16, 16, 32, 32, 64, 64, 64, 128, 128, 128].map(function(width, z) { - const patternCanvas = document.createElement('canvas'); - const patternContext = patternCanvas.getContext('2d'); - patternCanvas.width = width; - patternCanvas.height = patternCanvas.width; - patternContext.fillStyle = 'transparent'; - patternContext.strokeStyle = 'rgba(135, 90, 71, 1)'; - patternContext.lineWidth = z < 4 ? .5 : z <= 5 ? 1 : 2; - patternContext.beginPath(); - patternContext.moveTo(0, patternCanvas.height); - patternContext.lineTo(patternCanvas.width, 0); - patternContext.stroke(); - patternContext.moveTo(-patternCanvas.width, patternCanvas.height); - patternContext.lineTo(patternCanvas.width, -patternCanvas.height); - patternContext.stroke(); - patternContext.moveTo(0, 2*patternCanvas.height); - patternContext.lineTo(2*patternCanvas.width, 0); - patternContext.stroke(); - - const canvas = document.createElement('canvas'); - const context = canvas.getContext('2d'); - return new Style({ - zIndex: 14, - fill: new Fill({ - color: context.createPattern(patternCanvas, 'repeat'), - }), - stroke: width === 0 ? undefined : new Stroke({ - width: z < 4 ? .5 : z <= 5 ? 1 : 2, - color: [134, 90, 71, 1], - }), - }); - }), - }, - 'skydd.ovrigt_biotopskyddsomrade': { - popoverTitle: 'Biotopskydd utanför skogsmark', - popover: [ - ['NVR-ID', 'NVRID', { classes: ['feature-objid'] }], - ['Namn', 'NAMN'], - ['Skyddstyp', 'SKYDDSTYP'], - ['Beslutsstatus', 'BESLSTATUS'], - ['Beslutsdatum (bildande)', 'URSBESLDAT'], - ['Ursprungligt gällandedatum', 'URSGALLDAT'], - ['Senaste gällandedatum', 'SENGALLDAT'], - ['Förvaltare', 'FORVALTARE'], - ['IUCN-kategori', 'IUCNKAT'], - ['Diarienummer', 'DIARIENR', { classes: ['feature-attr-dnr'] }], - ['Lagrum', 'LAGRUM'], - ['Beslutsmyndighet', 'BESLMYND'], - ['Areal', 'geom_area', { fn: 'area' }], - ['Areal land', 'LAND_HA', { unit: 'ha' }], - ['Areal vatten', 'VATTEN_HA', { unit: 'ha' }], - ['Skogsmarksareal', 'SKOG_HA', { unit: 'ha' }], - ], - legend: { zoomLevel: 2 }, - style: [4, 8, 16, 16, 32, 32, 64, 64, 64, 128, 128, 128].map(function(width, z) { - const patternCanvas = document.createElement('canvas'); - const patternContext = patternCanvas.getContext('2d'); - patternCanvas.width = width; - patternCanvas.height = patternCanvas.width; - patternContext.fillStyle = 'transparent'; - patternContext.strokeStyle = 'rgba(255, 95, 0, 1)'; - patternContext.lineWidth = z < 4 ? .5 : z <= 5 ? 1 : 2; - patternContext.beginPath(); - patternContext.moveTo(0, patternCanvas.height); - patternContext.lineTo(patternCanvas.width, 0); - patternContext.stroke(); - patternContext.moveTo(-patternCanvas.width, patternCanvas.height); - patternContext.lineTo(patternCanvas.width, -patternCanvas.height); - patternContext.stroke(); - patternContext.moveTo(0, 2*patternCanvas.height); - patternContext.lineTo(2*patternCanvas.width, 0); - patternContext.stroke(); - - const canvas = document.createElement('canvas'); - const context = canvas.getContext('2d'); - return new Style({ - zIndex: 13, - fill: new Fill({ - color: context.createPattern(patternCanvas, 'repeat'), - }), - stroke: width === 0 ? undefined : new Stroke({ - width: z < 4 ? .5 : z <= 5 ? 1 : 2, - color: [255, 95, 0, 1], - }), - }); - }), - }, - 'skydd.naturminne_yta': { - popoverTitle: 'Naturminne (yta)', - popover: [ - ['NVR-ID', 'NVRID', { classes: ['feature-objid'] }], - ['Namn', 'NAMN'], - ['Skyddstyp', 'SKYDDSTYP'], - ['Beslutsstatus', 'BESLSTATUS'], - ['Beslutsdatum (bildande)', 'URSBESLDAT'], - ['Ursprungligt gällandedatum', 'URSGALLDAT'], - ['Senaste gällandedatum', 'SENGALLDAT'], - ['Förvaltare', 'FORVALTARE'], - ['IUCN-kategori', 'IUCNKAT'], - ['Diarienummer', 'DIARIENR', { classes: ['feature-attr-dnr'] }], - ['Lagrum', 'LAGRUM'], - ['Beslutsmyndighet', 'BESLMYND'], - ['Areal', 'geom_area', { fn: 'area' }], - ['Areal land', 'LAND_HA', { unit: 'ha' }], - ['Areal vatten', 'VATTEN_HA', { unit: 'ha' }], - ['Skogsmarksareal', 'SKOG_HA', { unit: 'ha' }], - ], - legend: { zoomLevel: 2 }, - style: [4, 8, 16, 16, 32, 32, 64, 64, 64, 128, 128, 128].map(function(width, z) { - const patternCanvas = document.createElement('canvas'); - const patternContext = patternCanvas.getContext('2d'); - patternCanvas.width = width; - patternCanvas.height = patternCanvas.width; - patternContext.fillStyle = 'transparent'; - patternContext.strokeStyle = 'rgba(113, 0, 116, 1)'; - patternContext.lineWidth = z < 4 ? .5 : z <= 5 ? 1 : 2; - patternContext.beginPath(); - patternContext.moveTo(0, patternCanvas.height); - patternContext.lineTo(patternCanvas.width, 0); - patternContext.stroke(); - patternContext.moveTo(-patternCanvas.width, patternCanvas.height); - patternContext.lineTo(patternCanvas.width, -patternCanvas.height); - patternContext.stroke(); - patternContext.moveTo(0, 2*patternCanvas.height); - patternContext.lineTo(2*patternCanvas.width, 0); - patternContext.stroke(); - - const canvas = document.createElement('canvas'); - const context = canvas.getContext('2d'); - return new Style({ - zIndex: 12, - fill: new Fill({ - color: context.createPattern(patternCanvas, 'repeat'), - }), - stroke: width === 0 ? undefined : new Stroke({ - width: z < 2 ? 1 : z < 4 ? 2 : z <= 5 ? 4 : 8, - color: [134, 0, 116, 1], - }), - }); - }), - }, - 'skydd.naturminne_punkt': { - popoverTitle: 'Naturminne (punkt)', - popover: [ - ['NVR-ID', 'NVRID', { classes: ['feature-objid'] }], - ['Namn', 'NAMN'], - ['Skyddstyp', 'SKYDDSTYP'], - ['Beslutsstatus', 'BESLSTATUS'], - ['Beslutsdatum (bildande)', 'URSBESLDAT'], - ['Ursprungligt gällandedatum', 'URSGALLDAT'], - ['Senaste gällandedatum', 'SENGALLDAT'], - ['Förvaltare', 'FORVALTARE'], - ['IUCN-kategori', 'IUCNKAT'], - ['Diarienummer', 'DIARIENR', { classes: ['feature-attr-dnr'] }], - ['Lagrum', 'LAGRUM'], - ['Beslutsmyndighet', 'BESLMYND'], - ['Skogsmarksareal', 'SKOG_HA', { unit: 'ha' }], - ], - legend: { zoomLevel: 6, type: 'point' }, - style: [undefined, undefined, undefined, undefined].concat([3, 4, 6, 8, 12, 16, 20, 24].map(function(width, z) { - return new Style({ - zIndex: 12, - image: new CircleStyle({ - radius: width, - fill: new Fill({ - color: 'rgba(113, 0, 116, .5)', - }), - stroke: new Stroke({ - width: Math.log2(width)/2, - color: 'rgba(113, 0, 116, 1)', - }), - }), - }); - })) - }, - 'skydd.interimistiskt_forbud': { - popoverTitle: 'Interimistiskt förbud', - popover: [ - ['NVR-ID', 'NVRID', { classes: ['feature-objid'] }], - ['Namn', 'NAMN'], - ['Skyddstyp', 'SKYDDSTYP'], - ['Beslutsstatus', 'BESLSTATUS'], - ['Beslutsdatum (bildande)', 'URSBESLDAT'], - ['Ursprungligt gällandedatum', 'URSGALLDAT'], - ['Senaste gällandedatum', 'SENGALLDAT'], - ['Förvaltare', 'FORVALTARE'], - ['IUCN-kategori', 'IUCNKAT'], - ['Diarienummer', 'DIARIENR', { classes: ['feature-attr-dnr'] }], - ['Lagrum', 'LAGRUM'], - ['Beslutsmyndighet', 'BESLMYND'], - ['Areal', 'geom_area', { fn: 'area' }], - ['Areal land', 'LAND_HA', { unit: 'ha' }], - ['Areal vatten', 'VATTEN_HA', { unit: 'ha' }], - ['Skogsmarksareal', 'SKOG_HA', { unit: 'ha' }], - ], - legend: { zoomLevel: 2 }, - style: [4, 8, 16, 16, 32, 32, 64, 64, 64, 128, 128, 128].map(function(width, z) { - const patternCanvas = document.createElement('canvas'); - const patternContext = patternCanvas.getContext('2d'); - patternCanvas.width = width; - patternCanvas.height = patternCanvas.width; - patternContext.fillStyle = 'transparent'; - patternContext.strokeStyle = 'rgba(168, 0, 0, 1)'; - patternContext.lineWidth = z < 4 ? .5 : z <= 5 ? 1 : 2; - patternContext.beginPath(); - patternContext.moveTo(0, patternCanvas.height); - patternContext.lineTo(patternCanvas.width, 0); - patternContext.stroke(); - patternContext.moveTo(-patternCanvas.width, patternCanvas.height); - patternContext.lineTo(patternCanvas.width, -patternCanvas.height); - patternContext.stroke(); - patternContext.moveTo(0, 2*patternCanvas.height); - patternContext.lineTo(2*patternCanvas.width, 0); - patternContext.stroke(); - - const canvas = document.createElement('canvas'); - const context = canvas.getContext('2d'); - return new Style({ - zIndex: 11, - fill: new Fill({ - color: context.createPattern(patternCanvas, 'repeat'), - }), - stroke: width === 0 ? undefined : new Stroke({ - width: z < 2 ? 1 : z < 4 ? 2 : z <= 5 ? 4 : 8, - color: [168, 0, 0, 1], - }), - }); - }), - }, - 'skydd.fageldirektivet': { - popoverTitle: 'Fågeldirektivet (SPA)', - popover: [ - ['Områdeskod', 'SITE_CODE', { classes: ['feature-objid'] }], - ['Namn', 'NAMN'], - ['Områdestyp', 'OMRADESTYP'], - ['Uppgiftslämnare', 'UPPLAMNARE'], - ['SPA-datum', 'SPA_DATUM'], - ['SCI-förslagsdatum', 'SCI_FORSL'], - ['SCI-datum', 'SCI_DATUM'], - ['SAC-datum', 'SAC_DATUM'], - ['Areal', 'geom_area', { fn: 'area' }], - ['Kvalitet', 'KVALITET'], - ['Kännetecken för området', 'KARAKTAR'], - ['Arter', 'ARTER'], - ['Naturtyper', 'NATURTYPER'], - ['Bevarandeplan', 'BEVPLAN', { fn: function(v) { - const a = document.createElement('a'); - a.href = v; - a.target = '_blank'; - const i = document.createElement('i'); - i.classList.add('bi', 'bi-box-arrow-up-right'); - a.appendChild(i); - return a; - }}], - ], - legend: { zoomLevel: 1 }, - style: [8, 16, 32, 32, 64, 64, 128, 128, 128, 256, 256, 256].map(function(width, z) { - const patternCanvas = document.createElement('canvas'); - const patternContext = patternCanvas.getContext('2d'); - patternCanvas.width = width*2; - patternCanvas.height = patternCanvas.width; - patternContext.fillStyle = 'transparent'; - patternContext.strokeStyle = 'rgba(230, 0, 0, 1)'; - patternContext.lineWidth = z < 4 ? .5 : z <= 5 ? 1 : 2; - patternContext.beginPath(); - patternContext.moveTo(0, patternCanvas.height); - patternContext.lineTo(patternCanvas.width, 0); - patternContext.stroke(); - patternContext.moveTo(-patternCanvas.width, patternCanvas.height); - patternContext.lineTo(patternCanvas.width, -patternCanvas.height); - patternContext.stroke(); - patternContext.moveTo(0, 2*patternCanvas.height); - patternContext.lineTo(2*patternCanvas.width, 0); - patternContext.stroke(); - patternContext.beginPath(); - patternContext.lineWidth *= 6; - patternContext.moveTo(-.5*patternCanvas.width, patternCanvas.height); - patternContext.lineTo(patternCanvas.width, -.5*patternCanvas.height); - patternContext.stroke(); - patternContext.moveTo(0, 1.5*patternCanvas.height); - patternContext.lineTo(1.5*patternCanvas.width, 0); - patternContext.stroke(); - - const canvas = document.createElement('canvas'); - const context = canvas.getContext('2d'); - return new Style({ - zIndex: 10, - fill: new Fill({ - color: context.createPattern(patternCanvas, 'repeat'), - }), - stroke: width === 0 ? undefined : new Stroke({ - width: z < 4 ? .5 : z <= 5 ? 1 : 2, - color: [230, 0, 0, 1], - }), - }); - }), - }, - 'skydd.habitatdirektivet': { - popoverTitle: 'Art- och habitatdirektivet (SCI)', - popover: [ - ['Områdeskod', 'SITE_CODE', { classes: ['feature-objid'] }], - ['Namn', 'NAMN'], - ['Områdestyp', 'OMRADESTYP'], - ['Uppgiftslämnare', 'UPPLAMNARE'], - ['SPA-datum', 'SPA_DATUM'], - ['SCI-förslagsdatum', 'SCI_FORSL'], - ['SCI-datum', 'SCI_DATUM'], - ['SAC-datum', 'SAC_DATUM'], - ['Areal', 'geom_area', { fn: 'area' }], - ['Kvalitet', 'KVALITET'], - ['Kännetecken för området', 'KARAKTAR'], - ['Arter', 'ARTER'], - ['Naturtyper', 'NATURTYPER'], - ['Bevarandeplan', 'BEVPLAN', { fn: function(v) { - const a = document.createElement('a'); - a.href = v; - a.target = '_blank'; - const i = document.createElement('i'); - i.classList.add('bi', 'bi-box-arrow-up-right'); - a.appendChild(i); - return a; - }}], - ], - legend: { zoomLevel: 1 }, - style: [8, 16, 32, 32, 64, 64, 128, 128, 128, 256, 256, 256].map(function(width, z) { - const patternCanvas = document.createElement('canvas'); - const patternContext = patternCanvas.getContext('2d'); - patternCanvas.width = width*2; - patternCanvas.height = patternCanvas.width; - patternContext.fillStyle = 'transparent'; - patternContext.strokeStyle = 'rgba(0, 77, 168, 1)'; - patternContext.lineWidth = z < 4 ? .5 : z <= 5 ? 1 : 2; - patternContext.beginPath(); - patternContext.moveTo(0, 0); - patternContext.lineTo(patternCanvas.width, patternCanvas.height); - patternContext.stroke(); - patternContext.moveTo(0, -patternCanvas.height); - patternContext.lineTo(2*patternCanvas.width, patternCanvas.height); - patternContext.stroke(); - patternContext.moveTo(-patternCanvas.width, 0); - patternContext.lineTo(patternCanvas.width, 2*patternCanvas.height); - patternContext.stroke(); - patternContext.beginPath(); - patternContext.lineWidth *= 6; - patternContext.moveTo(0, -.5*patternCanvas.height); - patternContext.lineTo(1.5*patternCanvas.width, patternCanvas.height); - patternContext.stroke(); - patternContext.moveTo(-.5*patternCanvas.width, 0); - patternContext.lineTo(patternCanvas.width, 1.5*patternCanvas.height); - patternContext.stroke(); - - const canvas = document.createElement('canvas'); - const context = canvas.getContext('2d'); - return new Style({ - zIndex: 10, - fill: new Fill({ - color: context.createPattern(patternCanvas, 'repeat'), - }), - stroke: width === 0 ? undefined : new Stroke({ - width: z < 4 ? .5 : z <= 5 ? 1 : 2, - color: [0, 77, 168, 1], - }), - }); - }), - }, - 'skydd.helcom': { - popoverTitle: 'Marina skyddade områden (Helcom MPA)', - popover: [ - ['Namn', 'NAME'], - ['Areal', 'geom_area', { fn: 'area' }], - ], - legend: { zoomLevel: 1 }, - style: [4, 8, 16, 16, 32, 32, 64, 64, 64, 128, 128, 128].map(function(width, z) { - const patternCanvas = document.createElement('canvas'); - const patternContext = patternCanvas.getContext('2d'); - patternCanvas.width = width; - patternCanvas.height = patternCanvas.width; - patternContext.fillStyle = 'rgba(130, 130, 130, 1)'; - const r = z < 5 ? (z+1)*.75 : z*.5; - patternContext.beginPath(); - patternContext.arc(.5*patternCanvas.width, .5*patternCanvas.height, r, 0, 2*Math.PI, true) - patternContext.fill(); - - const canvas = document.createElement('canvas'); - const context = canvas.getContext('2d'); - return new Style({ - zIndex: 9, - fill: new Fill({ - color: context.createPattern(patternCanvas, 'repeat'), - }), - stroke: width === 0 ? undefined : new Stroke({ - width: z < 2 ? 1 : z < 4 ? 2 : z <= 5 ? 4 : 8, - color: [130, 130, 130, 1], - }), - }); - }), - }, - 'skydd.ramsar': { - popoverTitle: 'Ramsar-områden (Våtmarkskonventionen)', - popover: [ - ['Ramsar-ID', 'RAMSAR_ID', { classes: ['feature-objid'] }], - ['Skyddstyp', 'SKYDDSTYP'], - ['Namn', 'NAMN'], - ['Areal', 'geom_area', { fn: 'area' }], - ['Areal land', 'LAND_HA', { unit: 'ha' }], - ['Areal vatten', 'VATTEN_HA', { unit: 'ha' }], - ['Skogsmarksareal', 'SKOG_HA', { unit: 'ha' }], - ['Ursprungligt beslutsdatum', 'URSPR_BESL'], - ['Senaste beslutsdatum', 'SEN_BESLUT'], - ['Rättsakt', 'LEGAL_ACT'], - ['Länk', 'LINK', { fn: function(v) { - if (v == null || v === '') { - return; - } - const a = document.createElement('a'); - a.href = v; - a.target = '_blank'; - const i = document.createElement('i'); - i.classList.add('bi', 'bi-box-arrow-up-right'); - a.appendChild(i); - return a; - }}], - ], - legend: { zoomLevel: 1 }, - style: [4, 8, 16, 16, 32, 32, 64, 64, 64, 128, 128, 128].map(function(width, z) { - const patternCanvas = document.createElement('canvas'); - const patternContext = patternCanvas.getContext('2d'); - patternCanvas.width = width; - patternCanvas.height = patternCanvas.width; - patternContext.fillStyle = 'rgba(195, 0, 255, 1)'; - const r = z < 5 ? (z+1)*.75 : z*.5; - patternContext.beginPath(); - patternContext.arc(.25*patternCanvas.width, .25*patternCanvas.height, r, 0, 2*Math.PI, true) - patternContext.fill(); - - const canvas = document.createElement('canvas'); - const context = canvas.getContext('2d'); - return new Style({ - zIndex: 9, - fill: new Fill({ - color: context.createPattern(patternCanvas, 'repeat'), - }), - stroke: width === 0 ? undefined : new Stroke({ - width: z < 2 ? 1 : z < 4 ? 2 : z <= 5 ? 4 : 8, - color: [195, 0, 255, 1], - }), - }); - }), - }, - 'skydd.ospar': { - popoverTitle: 'Marina skyddade områden (Ospar MPA)', - popover: [ - ['Ursprung', 'ORIGIN'], - ['N2000-namn', 'NAMN_N2000'], - ['MPA-ID', 'MPA_ID', { classes: ['feature-objid'] }], - ['MPA-namn', 'MPA_NAMN'], - ['N2000-ID', 'N2000_SITE', { classes: ['feature-objid'] }], - ['Areal', 'geom_area', { fn: 'area' }], - ], - legend: { zoomLevel: 1 }, - style: [4, 8, 16, 16, 32, 32, 64, 64, 64, 128, 128, 128].map(function(width, z) { - const patternCanvas = document.createElement('canvas'); - const patternContext = patternCanvas.getContext('2d'); - patternCanvas.width = width; - patternCanvas.height = patternCanvas.width; - patternContext.fillStyle = 'rgba(168, 0, 0, 1)'; - const r = z < 5 ? (z+1)*.75 : z*.5; - patternContext.beginPath(); - patternContext.arc(.25*patternCanvas.width, .75*patternCanvas.height, r, 0, 2*Math.PI, true) - patternContext.fill(); - - const canvas = document.createElement('canvas'); - const context = canvas.getContext('2d'); - return new Style({ - zIndex: 9, - fill: new Fill({ - color: context.createPattern(patternCanvas, 'repeat'), - }), - stroke: width === 0 ? undefined : new Stroke({ - width: z < 2 ? 1 : z < 4 ? 2 : z <= 5 ? 4 : 8, - color: [168, 0, 0, 1], - }), - }); - }), - }, - 'skydd.varldsarv': { - popoverTitle: 'Världsarv med mycket höga naturvärden (Unesco)', - popover: [ - ['Namn', 'NAMN'], - ['Areal', 'geom_area', { fn: 'area' }], - ], - legend: { zoomLevel: 1 }, - style: [4, 8, 16, 16, 32, 32, 64, 64, 64, 128, 128, 128].map(function(width, z) { - const patternCanvas = document.createElement('canvas'); - const patternContext = patternCanvas.getContext('2d'); - patternCanvas.width = width; - patternCanvas.height = patternCanvas.width; - patternContext.fillStyle = 'rgba(168, 0, 0, 1)'; - const r = z < 5 ? (z+1)*.75 : z*.5; - patternContext.beginPath(); - patternContext.arc(.75*patternCanvas.width, .25*patternCanvas.height, r, 0, 2*Math.PI, true) - patternContext.fill(); - - const canvas = document.createElement('canvas'); - const context = canvas.getContext('2d'); - return new Style({ - zIndex: 9, - fill: new Fill({ - color: context.createPattern(patternCanvas, 'repeat'), - }), - stroke: width === 0 ? undefined : new Stroke({ - width: z < 2 ? 1 : z < 4 ? 2 : z <= 5 ? 4 : 8, - color: [168, 0, 0, 1], - }), - }); - }), - }, - 'skydd.biosfarsomraden': { - popoverTitle: 'Biosfärsområde (Unesco)', - popover: [ - ['Namn', 'NAMN'], - ['Skyddstyp', 'SKYDDSTYP'], - ['Länk', 'LINK', { fn: function(v) { - if (v == null || v === '') { - return; - } - const a = document.createElement('a'); - a.href = v; - a.target = '_blank'; - const i = document.createElement('i'); - i.classList.add('bi', 'bi-box-arrow-up-right'); - a.appendChild(i); - return a; - }}], - ['Areal', 'geom_area', { fn: 'area' }], - ], - legend: { zoomLevel: 1 }, - style: [4, 8, 16, 16, 32, 32, 64, 64, 64, 128, 128, 128].map(function(width, z) { - const patternCanvas = document.createElement('canvas'); - const patternContext = patternCanvas.getContext('2d'); - patternCanvas.width = width; - patternCanvas.height = patternCanvas.width; - patternContext.fillStyle = 'rgba(131, 0, 219, 1)'; - const r = z < 5 ? (z+1)*.75 : z*.5; - patternContext.beginPath(); - patternContext.arc(.75*patternCanvas.width, .75*patternCanvas.height, r, 0, 2*Math.PI, true) - patternContext.fill(); - - const canvas = document.createElement('canvas'); - const context = canvas.getContext('2d'); - return new Style({ - zIndex: 9, - fill: new Fill({ - color: context.createPattern(patternCanvas, 'repeat'), - }), - stroke: width === 0 ? undefined : new Stroke({ - width: z < 2 ? 1 : z < 4 ? 2 : z <= 5 ? 4 : 8, - color: [131, 0, 219, 1], - }), - }); - }), - }, - 'skydd.naturvardsavtal': { - popoverTitle: 'Naturvårdsavtal (Naturvårdsverket, Länsstyrelsen)', - popover: [ - ['ID', 'ID', { classes: ['feature-objid'] }], - ['Namn', 'OBJNAMN'], - ['Fastighet', 'FASTBET', { classes: ['feature-objid'] }], - ['Giltig från', 'DATSTART'], - ['Giltig till', 'DATSLUT'], - ['Diarienummer', 'DIARIENRNV', { classes: ['feature-attr-dnr'] }], - ['Satus', 'STATUS'], - ['Areal', 'geom_area', { fn: 'area' }], - ], - legend: { zoomLevel: 1 }, - style: [8, 16, 32, 32, 64, 64, 128, 128, 128, 256, 256, 256].map(function(width, z) { - const patternCanvas = document.createElement('canvas'); - const patternContext = patternCanvas.getContext('2d'); - patternCanvas.width = width; - patternCanvas.height = patternCanvas.width; - patternContext.fillStyle = 'transparent'; - patternContext.strokeStyle = 'rgba(255, 0, 197, 1)'; - patternContext.lineWidth = z < 4 ? .5 : z <= 5 ? 1 : 2; - patternContext.beginPath(); - patternContext.moveTo(0, patternCanvas.height); - patternContext.lineTo(patternCanvas.width, 0); - patternContext.stroke(); - patternContext.moveTo(-patternCanvas.width, patternCanvas.height); - patternContext.lineTo(patternCanvas.width, -patternCanvas.height); - patternContext.stroke(); - patternContext.moveTo(0, 2*patternCanvas.height); - patternContext.lineTo(2*patternCanvas.width, 0); - patternContext.stroke(); - - const canvas = document.createElement('canvas'); - const context = canvas.getContext('2d'); - return new Style({ - zIndex: 21, - fill: new Fill({ - color: context.createPattern(patternCanvas, 'repeat'), - }), - stroke: width === 0 ? undefined : new Stroke({ - width: z < 4 ? .5 : z <= 5 ? 1 : 2, - color: [255, 0, 197, 1], - }), - }); - }), - }, - 'skydd.naturvardsavtal_skogsstyrelsen': { - popoverTitle: 'Naturvårdsavtal (Skogsstyrelsen)', - popover: [ - ['Ärendebeteckning', 'Beteckn', { classes: ['feature-objid'] }], - ['Registeringsår', 'ArendeAr'], - ['Biotopkategori', 'NvaTyp'], - ['Skogstyp', 'Naturtyp'], - ['Avtalsdatum', 'DatAvtal'], - ['Areal', 'geom_area', { fn: 'area' }], - ['Skogsmarksareal', 'AreaProd', { unit: 'ha' }], - ['Länk', 'Url', { fn: function(v) { - if (v == null | v === '') { - return; - } - const a = document.createElement('a'); - a.href = v; - a.target = '_blank'; - const i = document.createElement('i'); - i.classList.add('bi', 'bi-box-arrow-up-right'); - a.appendChild(i); - return a; - }}], - ['Undertyp', 'Undertyp'], - ], - legend: { zoomLevel: 2 }, - style: [4, 8, 16, 16, 32, 32, 64, 64, 64, 128, 128, 128].map(function(width, z) { - const patternCanvas = document.createElement('canvas'); - const patternContext = patternCanvas.getContext('2d'); - patternCanvas.width = width; - patternCanvas.height = patternCanvas.width; - patternContext.fillStyle = 'transparent'; - patternContext.strokeStyle = 'rgba(255, 0, 197, 1)'; - patternContext.lineWidth = z < 4 ? .5 : z <= 5 ? 1 : 2; - patternContext.beginPath(); - patternContext.moveTo(0, 0); - patternContext.lineTo(patternCanvas.width, patternCanvas.height); - patternContext.stroke(); - patternContext.moveTo(0, -patternCanvas.height); - patternContext.lineTo(2*patternCanvas.width, patternCanvas.height); - patternContext.stroke(); - patternContext.moveTo(-patternCanvas.width, 0); - patternContext.lineTo(patternCanvas.width, 2*patternCanvas.height); - patternContext.stroke(); - - const canvas = document.createElement('canvas'); - const context = canvas.getContext('2d'); - return new Style({ - zIndex: 20, - fill: new Fill({ - color: context.createPattern(patternCanvas, 'repeat'), - }), - stroke: width === 0 ? undefined : new Stroke({ - width: z < 4 ? .5 : z <= 5 ? 1 : 2, - color: [255, 0, 197, 1], - }), - }); - }), - }, - 'skydd.atervatningsavtal': { - popoverTitle: 'Återvätningsavtal', - popover: [ - ['Ärendebeteckning', 'Beteckn', { classes: ['feature-objid'] }], - ['Ärendeår', 'ArendeAr'], - ['Avtalat datum', 'AvtalatDatum'], - ['Areal', 'geom_area', { fn: 'area' }], - ['Länk', 'Url', { fn: function(v) { - if (v == null || v === '') { - return; - } - const a = document.createElement('a'); - a.href = v; - a.target = '_blank'; - const i = document.createElement('i'); - i.classList.add('bi', 'bi-box-arrow-up-right'); - a.appendChild(i); - return a; - }}], - ], - legend: { zoomLevel: 0 }, - style: [0, 1, 2, 3, 4, 5, 6].map(function(width) { - return new Style({ - zIndex: 5, - fill: new Fill({ - color: [255, 115, 0, .4], - }), - stroke: width === 0 ? undefined : new Stroke({ - width: .5, - color: [255, 115, 0, 1], - }), - }); - }) - .concat([7, 8, 9, 10, 11].map(function(width) { - const patternCanvas = document.createElement('canvas'); - const patternContext = patternCanvas.getContext('2d'); - patternCanvas.width = 16; - patternCanvas.height = patternCanvas.width; - patternContext.fillStyle = 'transparent'; - patternContext.strokeStyle = 'rgba(255, 115, 0, 1)'; - patternContext.lineWidth = 1; - patternContext.beginPath(); - patternContext.moveTo(0, 0); - patternContext.lineTo(patternCanvas.width, patternCanvas.height); - patternContext.stroke(); - patternContext.moveTo(0, -patternCanvas.height); - patternContext.lineTo(2*patternCanvas.width, patternCanvas.height); - patternContext.stroke(); - patternContext.moveTo(-patternCanvas.width, 0); - patternContext.lineTo(patternCanvas.width, 2*patternCanvas.height); - patternContext.stroke(); - - const canvas = document.createElement('canvas'); - const context = canvas.getContext('2d'); - return new Style({ - zIndex: 5, - fill: new Fill({ - color: context.createPattern(patternCanvas, 'repeat'), - }), - stroke: new Stroke({ - width: 1.5, - color: [255, 115, 0, 1], - }), - }); - })), - }, - 'nv.naturvarde_sks': { - popoverTitle: 'Objekt med naturvärden (Skogsstyrelsen)', - popover: [ - ['Ärendebeteckning', 'Beteckn', { classes: ['feature-objid'] }], - ['Namn', 'Objnamn'], - ['Datum för fältinventering', 'Datinv'], - ['Biotoptyp #1', 'Biotop1'], - ['Biotoptyp #2', 'Biotop2'], - ['Biotoptyp #3', 'Biotop3'], - ['Nyckelord #1 som beskriver objektet', 'Beskrivn1'], - ['Nyckelord #2 som beskriver objektet', 'Beskrivn2'], - ['Nyckelord #3 som beskriver objektet', 'Beskrivn3'], - ['Areal', 'geom_area', { fn: 'area' }], - ['Länk', 'Url', { fn: function(v) { - if (v == null || v === '') { - return; - } - const a = document.createElement('a'); - a.href = v; - a.target = '_blank'; - const i = document.createElement('i'); - i.classList.add('bi', 'bi-box-arrow-up-right'); - a.appendChild(i); - return a; - }}], - ], - legend: { zoomLevel: 0 }, - style: [0, 1, 2, 3, 4, 5].map(function(width) { - return new Style({ - zIndex: 6, - fill: new Fill({ - color: [255, 170, 0, .2], - }), - stroke: width === 0 ? undefined : new Stroke({ - width: .5, - color: [255, 170, 0, .8], - }), - }); - }) - .concat([6, 7, 8, 9, 10, 11].map(function(width) { - const patternCanvas = document.createElement('canvas'); - const patternContext = patternCanvas.getContext('2d'); - patternCanvas.width = 16; - patternCanvas.height = patternCanvas.width; - patternContext.fillStyle = 'transparent'; - patternContext.strokeStyle = 'rgba(255, 170, 0, 1)'; - patternContext.lineWidth = 1; - patternContext.beginPath(); - patternContext.moveTo(0, patternCanvas.height); - patternContext.lineTo(patternCanvas.width, 0); - patternContext.stroke(); - patternContext.moveTo(-patternCanvas.width, patternCanvas.height); - patternContext.lineTo(patternCanvas.width, -patternCanvas.height); - patternContext.stroke(); - patternContext.moveTo(0, 2*patternCanvas.height); - patternContext.lineTo(2*patternCanvas.width, 0); - patternContext.stroke(); - - const canvas = document.createElement('canvas'); - const context = canvas.getContext('2d'); - return new Style({ - zIndex: 6, - fill: new Fill({ - color: context.createPattern(patternCanvas, 'repeat'), - }), - stroke: new Stroke({ - width: 1.5, - color: [255, 170, 0, 1], - }), - }); - })), - }, - 'nv.nyckelbiotop': { - popoverTitle: 'Nyckelbiotop (Skogsstyrelsen)', - popover: [ - ['Ärendebeteckning', 'Beteckn', { classes: ['feature-objid'] }], - ['Namn', 'Objnamn'], - ['Datum för fältinventering', 'Datinv'], - ['Biotoptyp #1', 'Biotop1'], - ['Biotoptyp #2', 'Biotop2'], - ['Biotoptyp #3', 'Biotop3'], - ['Nyckelord #1 som beskriver objektet', 'Beskrivn1'], - ['Nyckelord #2 som beskriver objektet', 'Beskrivn2'], - ['Nyckelord #3 som beskriver objektet', 'Beskrivn3'], - ['Nyckelord #4 som beskriver objektet', 'Beskrivn4'], - ['Nyckelord #5 som beskriver objektet', 'Beskrivn5'], - ['Nyckelord #6 som beskriver objektet', 'Beskrivn6'], - ['Nyckelord #7 som beskriver objektet', 'Beskrivn7'], - ['Nyckelord #8 som beskriver objektet', 'Beskrivn8'], - ['Areal', 'geom_area', { fn: 'area' }], - ['Länk', 'Url', { fn: function(v) { - if (v == null || v === '') { - return; - } - const a = document.createElement('a'); - a.href = v; - a.target = '_blank'; - const i = document.createElement('i'); - i.classList.add('bi', 'bi-box-arrow-up-right'); - a.appendChild(i); - return a; - }}], - ], - legend: { zoomLevel: 0 }, - style: [0, 1, 2, 3, 4, 5].map(function(width) { - return new Style({ - zIndex: 6, - fill: new Fill({ - color: [217, 148, 9, .2], - }), - stroke: width === 0 ? undefined : new Stroke({ - width: .5, - color: [217, 148, 9, .8], - }), - }); - }) - .concat([6, 7, 8, 9, 10, 11].map(function(width) { - const patternCanvas = document.createElement('canvas'); - const patternContext = patternCanvas.getContext('2d'); - patternCanvas.width = 16; - patternCanvas.height = patternCanvas.width; - patternContext.fillStyle = 'transparent'; - patternContext.strokeStyle = 'rgba(217, 148, 9, 1)'; - patternContext.lineWidth = 1; - patternContext.beginPath(); - patternContext.moveTo(0, patternCanvas.height); - patternContext.lineTo(patternCanvas.width, 0); - patternContext.stroke(); - patternContext.moveTo(-patternCanvas.width, patternCanvas.height); - patternContext.lineTo(patternCanvas.width, -patternCanvas.height); - patternContext.stroke(); - patternContext.moveTo(0, 2*patternCanvas.height); - patternContext.lineTo(2*patternCanvas.width, 0); - patternContext.stroke(); - - const canvas = document.createElement('canvas'); - const context = canvas.getContext('2d'); - return new Style({ - zIndex: 6, - fill: new Fill({ - color: context.createPattern(patternCanvas, 'repeat'), - }), - stroke: new Stroke({ - width: 1.5, - color: [217, 148, 9, 1], - }), - }); - })), - }, - 'nv.nyckelbiotop_storskogsbruk': { - popoverTitle: 'Nyckelbiotop (storskogsbruket)', - popover: [ - ['Uppgifter lämnade av', 'Org'], - ['Inkom datum', 'InkomDatum'], - ['Areal', 'geom_area', { fn: 'area' }], - ['Länk', 'Url', { fn: function(v) { - if (v == null || v === '') { - return; - } - const a = document.createElement('a'); - a.href = v; - a.target = '_blank'; - const i = document.createElement('i'); - i.classList.add('bi', 'bi-box-arrow-up-right'); - a.appendChild(i); - return a; - }}], - ], - legend: { zoomLevel: 0 }, - style: [0, 1, 2, 3, 4, 5].map(function(width) { - return new Style({ - zIndex: 6, - fill: new Fill({ - color: [217, 148, 9, .2], - }), - stroke: width === 0 ? undefined : new Stroke({ - width: .5, - color: [217, 148, 9, .8], - }), - }); - }) - .concat([6, 7, 8, 9, 10, 11].map(function(width) { - const patternCanvas = document.createElement('canvas'); - const patternContext = patternCanvas.getContext('2d'); - patternCanvas.width = 16; - patternCanvas.height = patternCanvas.width; - patternContext.fillStyle = 'transparent'; - patternContext.strokeStyle = 'rgba(217, 148, 9, 1)'; - patternContext.lineWidth = 1; - patternContext.beginPath(); - patternContext.moveTo(0, 0); - patternContext.lineTo(patternCanvas.width, patternCanvas.height); - patternContext.stroke(); - patternContext.moveTo(0, -patternCanvas.height); - patternContext.lineTo(2*patternCanvas.width, patternCanvas.height); - patternContext.stroke(); - patternContext.moveTo(-patternCanvas.width, 0); - patternContext.lineTo(patternCanvas.width, 2*patternCanvas.height); - patternContext.stroke(); - - const canvas = document.createElement('canvas'); - const context = canvas.getContext('2d'); - return new Style({ - zIndex: 6, - fill: new Fill({ - color: context.createPattern(patternCanvas, 'repeat'), - }), - stroke: new Stroke({ - width: 1.5, - color: [217, 148, 9, 1], - }), - }); - })), - }, - 'nv.sumpskog': { - popoverTitle: 'Sumpskog', - popover: [ - ['Objektnamn', 'Namn'], - ['Skogstyp', 'Tradtext'], - ['Hydrologisk typ', 'Hydrtext'], - ['Klass på delobjektet', 'Delklass'], - ['Klass på objektet', 'Klassu'], - ['Andel löv', 'Lovandel'], - ['Andel öppet vatten', 'Andelva'], - ['Krontäckning', 'Krontakn'], - ['Huggningsklass', 'Huggklas'], - ['Ingrepp på delobjekt (max 4)', 'Ingrepp'], - ['Grad av påverkan på delobjekt (max 4)', 'Ingrpavv'], - ['Nyckelord på objektnivå', 'Objnyck'], - ['Nyckelord på delobjektsnivå', 'Delnyck'], - ['Flygbildsår', 'Flygar'], - ['Datum för fältbesök', 'Faltdat'], - ['Inventeringsteknik', 'Invtekn'], - ['Inventeringdatum', 'Invdat'], - ['Ansvarig myndighet', 'Ansvmynd'], - ['Areal', 'geom_area', { fn: 'area' }], - ['Länk', 'Url', { fn: function(v) { - if (v == null || v === '') { - return; - } - const a = document.createElement('a'); - a.href = v; - a.target = '_blank'; - const i = document.createElement('i'); - i.classList.add('bi', 'bi-box-arrow-up-right'); - a.appendChild(i); - return a; - }}], - ], - legend: { zoomLevel: 5 }, - style: [.5, 1, 1.5, 1.5, 2, 2, 2.5, 2.5, 3, 3.5, 4, 5].map(function(width, z) { - const patternCanvas = document.createElement('canvas'); - const patternContext = patternCanvas.getContext('2d'); - const w = Math.max(1, width); - patternCanvas.width = z < 2 ? 2 : z < 4 ? 4 : z <= 5 ? 6 : 8; - patternCanvas.height = patternCanvas.width; - patternContext.fillStyle = 'transparent'; - patternContext.strokeStyle = 'rgba(158, 200, 215, 1)'; - patternContext.lineWidth = w; - patternContext.beginPath(); - patternContext.moveTo(0, 0); - patternContext.lineTo(patternCanvas.width, 0); - patternContext.stroke(); - - const canvas = document.createElement('canvas'); - const context = canvas.getContext('2d'); - return new Style({ - zIndex: 5, - fill: new Fill({ - color: context.createPattern(patternCanvas, 'repeat'), - }), - stroke: width === 0 ? undefined : new Stroke({ - width: w/2, - color: [158, 200, 215, 1], - }), - }); - }), - }, - 'nv.pagaende_naturreservatsbildning': { - popoverTitle: 'Pågående naturreservatsbildning', - popover: [ - ['Objektnamn', 'NAMN'], - ['Senast justerat', 'GRANSJUST'], /* XXX unclear what "GRANSJUST" means, just a guess */ - ['Areal', 'geom_area', { fn: 'area' }], - ], - legend: { zoomLevel: 1 }, - style: [8, 16, 32, 32, 64, 64, 128, 128, 128, 256, 256, 256].map(function(width, z) { - const patternCanvas = document.createElement('canvas'); - const patternContext = patternCanvas.getContext('2d'); - patternCanvas.width = width; - patternCanvas.height = patternCanvas.width; - patternContext.fillStyle = 'transparent'; - patternContext.setLineDash([width/4, width/4]); - patternContext.strokeStyle = 'rgba(7, 181, 7, 1)'; - patternContext.lineWidth = z < 4 ? .5 : z <= 5 ? 1 : 2; - patternContext.beginPath(); - patternContext.moveTo(width/4, 0); - patternContext.lineTo(width/4, patternCanvas.height); - patternContext.stroke(); - patternContext.beginPath(); - patternContext.lineDashOffset = width/4; - patternContext.moveTo(3*width/4, 0); - patternContext.lineTo(3*width/4, patternCanvas.height); - patternContext.stroke(); - - const canvas = document.createElement('canvas'); - const context = canvas.getContext('2d'); - return new Style({ - zIndex: 10, - fill: new Fill({ - color: context.createPattern(patternCanvas, 'repeat'), - }), - stroke: width === 0 ? undefined : new Stroke({ - width: z < 2 ? 1 : z < 4 ? 2 : z <= 5 ? 3 : 4, - color: [7, 181, 7, 1], - lineDash: [width/8, width/4], - }), - }); - }), - }, - 'nv.snus': { - popoverTitle: 'Skyddsvärd statlig skog', - popover: [ - ['Objektnamn', 'NAMN'], - ['År', 'AR'], - ['Naturgeografisk region', 'NATURGEOGR', { classes: ['feature-objid'] }], - ['Objektskategori', 'OBJEKTKATE', { classes: ['feature-objid'] }], - ['Markägare', 'MARKAGARE'], - ['Areal värdekärna', 'VARDEKARNA', { unit: 'ha' }], - ['Areal utvecklingsmark', 'UTV_MARK', { unit: 'ha' }], - ['Totalareal', 'TOTAL_AREA', { unit: 'ha' }], - ['Areal land', 'LAND', { unit: 'ha' }], - ['Areal vatten', 'VATTEN', { unit: 'ha' }], - ['Areal produktiv skogsmark', 'PROD_SKOG', { unit: 'ha' }], - ['Areal produktiv skogsmark ovanför fjällnära gräns', 'SKOG_O_FJG', { unit: 'ha' }], - ['Areal produktiv skogsmark nedanför fjällnära gräns', 'SKOG_N_FJG', { unit: 'ha' }], - ['Areal skyddszon', 'SKYDDSZON', { unit: 'ha' }], - ['Areal arronderingsmark', 'ARRO_MARK', { unit: 'ha' }], - ['Kriterier för urval', 'KRITERIER'], - ['Beskrivning av området', 'BESKRIVN'], - ['Länsstyrelsens bedömning', 'LST_BEDOMN'], - ['Källor', 'KALLOR'], - ], - legend: { zoomLevel: 1 }, - style: [.5, 1, 1.5, 1.5, 2, 2, 2.5, 2.5, 3, 3.5, 4, 5].map(function(width, z) { - return new Style({ - zIndex: 4, - fill: new Fill({ - color: [168,168,0,.2], - }), - stroke: width === 0 ? undefined : new Stroke({ - width: width, - color: [168,77,0,.75], - }), - }); - }), - }, - - 'ri.naturvard': { - popoverTitle: 'Riksintresse naturvård', - popover: [ - ['Namn', 'NAMN'], - ['Skydd', 'SKYDD'], - ['Ämnesområde', 'AMNESOMRAD'], - ['Beskrivning', 'BESKRIVNIN', { fn: function(v) { - if (v == null || !(v.startsWith('http://') || v.startsWith('https://'))) { - return v; - } - const a = document.createElement('a'); - a.href = v; - a.target = '_blank'; - const i = document.createElement('i'); - i.classList.add('bi', 'bi-box-arrow-up-right'); - a.appendChild(i); - return a; - }}], - ['Lagrum', 'LAGRUM'], - ['Beslutsdatum', 'BESLUTSDAT'], - ['Original-ID', 'ORGINALID', { classes: ['feature-objid'] }], - ['Riks-ID', 'RIKSID', { classes: ['feature-objid'] }], - ['Areal', 'geom_area', { fn: 'area' }], - ], - legend: { zoomLevel: 0 }, - style: [8, 16, 32, 32, 64, 64, 128, 128, 128, 256, 256, 256].map(function(width, z) { - const patternCanvas = document.createElement('canvas'); - const patternContext = patternCanvas.getContext('2d'); - patternCanvas.width = width; - patternCanvas.height = patternCanvas.width; - patternContext.fillStyle = 'transparent'; - patternContext.strokeStyle = 'rgba(154, 230, 0, 1)'; - patternContext.lineWidth = z < 4 ? .5 : z <= 5 ? 1 : 2; - patternContext.beginPath(); - patternContext.moveTo(0, 0); - patternContext.lineTo(patternCanvas.width, patternCanvas.height); - patternContext.stroke(); - patternContext.moveTo(0, -patternCanvas.height); - patternContext.lineTo(2*patternCanvas.width, patternCanvas.height); - patternContext.stroke(); - patternContext.moveTo(-patternCanvas.width, 0); - patternContext.lineTo(patternCanvas.width, 2*patternCanvas.height); - patternContext.stroke(); - - const canvas = document.createElement('canvas'); - const context = canvas.getContext('2d'); - return new Style({ - zIndex: 8, - fill: new Fill({ - color: context.createPattern(patternCanvas, 'repeat'), - }), - stroke: width === 0 ? undefined : new Stroke({ - width: z < 2 ? 1 : z < 4 ? 2 : z <= 5 ? 4 : 8, - color: [154, 230, 0, 1], - }), - }); - }), - }, - 'ri.friluftsliv': { - popoverTitle: 'Riksintresse friluftsliv', - popover: [ - ['Namn', 'NAMN'], - ['Skydd', 'SKYDD'], - ['Ämnesområde', 'AMNESOMR'], - ['Områdesnummer', 'OMRADESNR', { classes: ['feature-objid'] }], - ['Länk värdebeskrivning', 'LANK_VARDE', { fn: function(v) { - if (v == null | v === '') { - return; - } - const a = document.createElement('a'); - a.href = v; - a.target = '_blank'; - const i = document.createElement('i'); - i.classList.add('bi', 'bi-box-arrow-up-right'); - a.appendChild(i); - return a; - }}], - ['Lagrum', 'LAGRUM'], - ['Beslutsdatum', 'BESLDATUM'], - ['Ärendenummer', 'ARENDENR', { classes: ['feature-attr-dnr'] }], - ['Länk, beslut', 'LANK_BESLU', { fn: function(v) { - if (v == null | v === '') { - return; - } - const a = document.createElement('a'); - a.href = v; - a.target = '_blank'; - const i = document.createElement('i'); - i.classList.add('bi', 'bi-box-arrow-up-right'); - a.appendChild(i); - return a; - }}], - ['Aktivitet', 'AKTIVITET'], - ['Naturtyp', 'NATURTYP'], - ['Areal', 'geom_area', { fn: 'area' }], - ['Areal land', 'AREA_LAND_', { unit: 'ha' }], - ['Areal vatten', 'AREA_VATTE', { unit: 'ha' }], - ], - legend: { zoomLevel: 0 }, - style: [8, 16, 32, 32, 64, 64, 128, 128, 128, 256, 256, 256].map(function(width, z) { - const patternCanvas = document.createElement('canvas'); - const patternContext = patternCanvas.getContext('2d'); - patternCanvas.width = width; - patternCanvas.height = patternCanvas.width; - patternContext.fillStyle = 'transparent'; - patternContext.strokeStyle = 'rgba(0, 127, 232, 1)'; - patternContext.lineWidth = z < 4 ? .5 : z <= 5 ? 1 : 2; - patternContext.beginPath(); - patternContext.moveTo(0, 0); - patternContext.lineTo(patternCanvas.width, patternCanvas.height); - patternContext.stroke(); - patternContext.moveTo(0, -patternCanvas.height); - patternContext.lineTo(2*patternCanvas.width, patternCanvas.height); - patternContext.stroke(); - patternContext.moveTo(-patternCanvas.width, 0); - patternContext.lineTo(patternCanvas.width, 2*patternCanvas.height); - patternContext.stroke(); - - const canvas = document.createElement('canvas'); - const context = canvas.getContext('2d'); - return new Style({ - zIndex: 8, - fill: new Fill({ - color: context.createPattern(patternCanvas, 'repeat'), - }), - stroke: width === 0 ? undefined : new Stroke({ - width: z < 2 ? 1 : z < 4 ? 2 : z <= 5 ? 4 : 8, - color: [0, 127, 232, 1], - }), - }); - }), - }, - 'ri.rorligt_friluftsliv': { - popoverTitle: 'Riksintresse rörligt friluftsliv (MB 4 kap 1§ och 2§)', - popover: [ - ['Namn', 'NAMN'], - //['Original-ID', 'ORIGINALID', { classes: ['feature-objid'] }], - ['Beskrivning', 'BESKRIVNIN'], - //['Metodbeskrivning', 'METODBESKR'], - //['Tillk. datum', 'TILLKDATUM'], - //['Rev. datum', 'REVDATUM'], - ['Anmärkning', 'ANM'], - ['Länk', 'OBJEKTLANK', { fn: function(v) { - if (v == null || v === '') { - return; - } - const a = document.createElement('a'); - a.href = v; - a.target = '_blank'; - const i = document.createElement('i'); - i.classList.add('bi', 'bi-box-arrow-up-right'); - a.appendChild(i); - return a; - }}], - ['Areal', 'geom_area', { fn: 'area' }], - ['Referens', 'REFERENS'], - ], - legend: { zoomLevel: 0 }, - style: [8, 16, 32, 32, 64, 64, 128, 128, 128, 256, 256, 256].map(function(width, z) { - const patternCanvas = document.createElement('canvas'); - const patternContext = patternCanvas.getContext('2d'); - patternCanvas.width = width; - patternCanvas.height = patternCanvas.width; - patternContext.fillStyle = 'rgba(187, 227, 212, .25)'; - patternContext.fillRect(0, 0, patternCanvas.width, patternCanvas.height); - patternContext.strokeStyle = 'rgba(56, 151, 117, 1)'; - patternContext.lineWidth = z < 4 ? .5 : z <= 5 ? 1 : 2; - patternContext.beginPath(); - patternContext.moveTo(0, patternCanvas.height); - patternContext.lineTo(patternCanvas.width, 0); - patternContext.stroke(); - patternContext.moveTo(-patternCanvas.width, patternCanvas.height); - patternContext.lineTo(patternCanvas.width, -patternCanvas.height); - patternContext.stroke(); - patternContext.moveTo(0, 2*patternCanvas.height); - patternContext.lineTo(2*patternCanvas.width, 0); - patternContext.stroke(); - - const canvas = document.createElement('canvas'); - const context = canvas.getContext('2d'); - return new Style({ - zIndex: 8, - fill: new Fill({ - color: context.createPattern(patternCanvas, 'repeat'), - }), - stroke: width === 0 ? undefined : new Stroke({ - width: z < 2 ? 2 : z < 4 ? 4 : z <= 5 ? 8 : 16, - color: [56, 151, 117, 1], - lineDash: [width/4, width/3], - }), - }); - }), - }, - 'ri.obruten_kust': { - popoverTitle: 'Riksintresse obruten kust (MB 4 kap 3§)', - popover: [ - ['Namn', 'NAMN'], - //['Original-ID', 'ORIGINALID', { classes: ['feature-objid'] }], - ['Beskrivning', 'BESKRIVNIN'], - //['Metodbeskrivning', 'METODBESKR'], - //['Tillk. datum', 'TILLKDATUM'], - //['Rev. datum', 'REVDATUM'], - ['Anmärkning', 'ANM'], - ['Objekttyp', 'OBJTYP'], - ['Länk', 'OBJEKTLANK', { fn: function(v) { - if (v == null || v === '') { - return; - } - const a = document.createElement('a'); - a.href = v; - a.target = '_blank'; - const i = document.createElement('i'); - i.classList.add('bi', 'bi-box-arrow-up-right'); - a.appendChild(i); - return a; - }}], - ['Areal', 'geom_area', { fn: 'area' }], - ['Referens', 'REFERENS'], - ], - legend: { zoomLevel: 0 }, - style: [8, 16, 32, 32, 64, 64, 128, 128, 128, 256, 256, 256].map(function(width, z) { - const patternCanvas = document.createElement('canvas'); - const patternContext = patternCanvas.getContext('2d'); - patternCanvas.width = width; - patternCanvas.height = patternCanvas.width; - patternContext.fillStyle = 'rgba(227, 227, 187, .25)'; - patternContext.fillRect(0, 0, patternCanvas.width, patternCanvas.height); - patternContext.strokeStyle = 'rgba(156, 158, 56, 1)'; - patternContext.lineWidth = z < 4 ? .5 : z <= 5 ? 1 : 2; - patternContext.beginPath(); - patternContext.moveTo(0, 0); - patternContext.lineTo(patternCanvas.width, patternCanvas.height); - patternContext.stroke(); - patternContext.moveTo(0, -patternCanvas.height); - patternContext.lineTo(2*patternCanvas.width, patternCanvas.height); - patternContext.stroke(); - patternContext.moveTo(-patternCanvas.width, 0); - patternContext.lineTo(patternCanvas.width, 2*patternCanvas.height); - patternContext.stroke(); - - const canvas = document.createElement('canvas'); - const context = canvas.getContext('2d'); - return new Style({ - zIndex: 8, - fill: new Fill({ - color: context.createPattern(patternCanvas, 'repeat'), - }), - stroke: width === 0 ? undefined : new Stroke({ - width: z < 2 ? 2 : z < 4 ? 4 : z <= 5 ? 8 : 16, - color: [156, 158, 56, 1], - lineDash: [width/4, width/3], - }), - }); - }), - }, - 'ri.obrutet_fjall': { - popoverTitle: 'Riksintresse obrutet fjäll (MB 4 kap 5§)', - popover: [ - ['Namn', 'NAMN'], - //['Original-ID', 'ORIGINALID', { classes: ['feature-objid'] }], - ['Beskrivning', 'BESKRIVNIN'], - ['Metodbeskrivning', 'METODBESKR'], - ['Tillk. datum', 'TILLKDATUM'], - //['Rev. datum', 'REVDATUM'], - ['Länk', 'OBJEKTLANK', { fn: function(v) { - if (v == null || v === '') { - return; - } - const a = document.createElement('a'); - a.href = v; - a.target = '_blank'; - const i = document.createElement('i'); - i.classList.add('bi', 'bi-box-arrow-up-right'); - a.appendChild(i); - return a; - }}], - ['Areal', 'geom_area', { fn: 'area' }], - ['Referens', 'REFERENS'], - ], - legend: { zoomLevel: 0 }, - style: [8, 16, 32, 32, 64, 64, 128, 128, 128, 256, 256, 256].map(function(width, z) { - const patternCanvas = document.createElement('canvas'); - const patternContext = patternCanvas.getContext('2d'); - patternCanvas.width = width; - patternCanvas.height = patternCanvas.width; - patternContext.fillStyle = 'rgba(255, 255, 209, .25)'; - patternContext.fillRect(0, 0, patternCanvas.width, patternCanvas.height); - patternContext.strokeStyle = 'rgba(219, 183, 60, 1)'; - patternContext.lineWidth = z < 4 ? .5 : z <= 5 ? 1 : 2; - patternContext.beginPath(); - patternContext.moveTo(0, 0); - patternContext.lineTo(patternCanvas.width, patternCanvas.height); - patternContext.stroke(); - patternContext.moveTo(0, -patternCanvas.height); - patternContext.lineTo(2*patternCanvas.width, patternCanvas.height); - patternContext.stroke(); - patternContext.moveTo(-patternCanvas.width, 0); - patternContext.lineTo(patternCanvas.width, 2*patternCanvas.height); - patternContext.stroke(); - - const canvas = document.createElement('canvas'); - const context = canvas.getContext('2d'); - return new Style({ - zIndex: 8, - fill: new Fill({ - color: context.createPattern(patternCanvas, 'repeat'), - }), - stroke: width === 0 ? undefined : new Stroke({ - width: z < 2 ? 2 : z < 4 ? 4 : z <= 5 ? 8 : 16, - color: [219, 183, 60, 1], - lineDash: [width/4, width/3], - }), - }); - }), - }, - 'ri.skyddade_vattendrag': { - popoverTitle: 'Riksintresse skyddade vattendrag (MB 4 kap 6§)', - popover: [ - ['Namn', 'NAMN'], - //['Original-ID', 'ORIGINALID', { classes: ['feature-objid'] }], - ['Beskrivning', 'BESKRIVNIN'], - ['Metodbeskrivning', 'METODBESKR'], - ['Tillk. datum', 'TILLKDATUM'], - ['Rev. datum', 'REVDATUM'], - ['Anmärkning', 'ANM'], - ['Digitaliseringsskala', 'DIG_SKALA'], - ['Länk', 'OBJEKTLANK', { fn: function(v) { - if (v == null || v === '') { - return; - } - const a = document.createElement('a'); - a.href = v; - a.target = '_blank'; - const i = document.createElement('i'); - i.classList.add('bi', 'bi-box-arrow-up-right'); - a.appendChild(i); - return a; - }}], - ['Areal', 'geom_area', { fn: 'area' }], - ['Referens', 'REFERENS'], - ], - legend: { zoomLevel: 0 }, - style: [8, 16, 32, 32, 64, 64, 128, 128, 128, 256, 256, 256].map(function(width, z) { - return new Style({ - zIndex: 8, - fill: new Fill({ - color: [102, 157, 240, .25], - }), - stroke: width === 0 ? undefined : new Stroke({ - width: z < 2 ? 2 : z < 4 ? 4 : z <= 5 ? 8 : 16, - color: [41, 109, 197, 1], - lineDash: [width/4, width/3], - }), - }); - }), - }, - - 'ren.betesomrade': { - popoverTitle: 'Samebyarnas betesområde', - popover: [ - ['Sameby', 'NAMN'], - ['Samebys typ', 'SAMEBY_TYP'], - ['Signatur', 'SIGNATUR'], - ['Aktualitet', 'AKTUALITET'], - ], - legend: { zoomLevel: 0 }, - style: [1, 1.5, 2, 3, 3.5, 4, 5, 5, 6, 7, 8, 10].map(function(width, z) { - return new Style({ - zIndex: 4, - fill: new Fill({ - /* transparent fill so clicking the inside of the polygon triggers a popover */ - /* XXX could also use a custom renderer but that doesn't seem to work */ - color: [0, 0, 0, 0], - }), - stroke: width === 0 ? undefined : new Stroke({ - width: width, - color: [179, 153, 102, 1], - }), - }); - }), - }, - 'ren.flyttled': { - popoverTitle: 'Samebyarnas markanvändningsredovisning \u2013 flyttled', - popover: [ - ['Led-ID', 'LED_ID', { classes: ['feature-objid'], fn: (v) => v === 0 ? '' : v }], - ['Sameby #1', 'SAMEBY1'], - ['Sameby #2', 'SAMEBY2'], - ['Sameby #3', 'SAMEBY3'], - ['Beskrivning', 'BESKRIVNIN'], - ['Årstid', 'ARSTID'], - ['Riksintresse', 'RIKSINTR'], - ['Fast led', 'FAST_LED'], - ['Aktualitet', 'AKTUALITET'], - ['Signatur', 'SIGNATUR'], - ['Ledlängd', 'geom_length', { fn: 'length' }], - ], - legend: { zoomLevel: 2, type: 'linestring' }, - style: [.75, 1, 1.5, 2, 3, 4, 5, 5, 6, 7, 8, 10].map(function(width, z) { - return new Style({ - zIndex: 7, - stroke: new Stroke({ - width: 2*width, - color: [119, 99, 59, 1], - lineDash: [4 * width], - }), - }); - }), - }, - 'ren.riks_ren': { - popoverTitle: 'Riksintresse rennäring', - popover: [ - ['Lagrum', 'LAGRUM'], - ['Aktualitet', 'AKTUALITET'], - ['Signatur', 'SIGNATUR'], - ['Areal', 'geom_area', { fn: 'area' }], - ], - legend: { zoomLevel: 1 }, - style: [.5, 1, 1.5, 1.5, 2, 2, 2.5, 2.5, 3, 3.5, 4, 5].map(function(width, z) { - const patternCanvas = document.createElement('canvas'); - const patternContext = patternCanvas.getContext('2d'); - patternCanvas.width = z < 4 ? 4 : z <= 5 ? 8 : Math.pow(2, Math.round(Math.log2(width) + 3)); - patternCanvas.height = patternCanvas.width; - patternContext.fillStyle = 'transparent'; - patternContext.strokeStyle = 'rgba(179, 153, 102, 1)'; - patternContext.lineWidth = Math.max(1, width/2); - patternContext.beginPath(); - patternContext.moveTo(0, 0); - patternContext.lineTo(patternCanvas.width, 0); - patternContext.stroke(); - - const canvas = document.createElement('canvas'); - const context = canvas.getContext('2d'); - return new Style({ - zIndex: 6, - fill: new Fill({ - color: context.createPattern(patternCanvas, 'repeat'), - }), - stroke: width === 0 ? undefined : new Stroke({ - width: width, - color: [179, 153, 102, 1], - }), - }); - }), - }, - 'ren.omr_riks': { - popoverTitle: '(Kärn)områden av riksintresse rennäring', - popover: [ - ['Områdes-ID', 'OMR_NR', { classes: ['feature-objid'] }], - ['Länk', 'LANK'], - ['Årets runt', 'ARET_RUNT'], - ['Sameby', 'SAMEBY'], - ['Ansvarig', 'ANSVARIG'], - ['Aktualitet', 'AKTUALITET'], - ['Signatur', 'SIGNATUR'], - ['Areal', 'geom_area', { fn: 'area' }], - ], - legend: { zoomLevel: 2 }, - style: [.5, .5, 1, 1, 1, 1.5, 1.5, 1.5, 2, 2, 2, 2].map(function(width, z) { - return new Style({ - zIndex: 5, - fill: new Fill({ - color: [203, 190, 163, Math.max((.3-.5)/8 * z + .5, 0)], - }), - stroke: width === 0 ? undefined : new Stroke({ - width: width, - color: [179, 153, 102, 1], - }), - }); - }), - }, - - /* Documentation at - * https://www.smhi.se/polopoly_fs/1.34541!/dammprod%202013_3%2C%20beskrivning%2C%20SVAR2012_2.pdf - * */ - 'misc.dammar': { - popoverTitle: 'Damm', - popover: [ - ['Dammenhetens namn', 'DNamn'], - ['Dammanläggningens namn', 'Namn'], - ['Länsnr', 'LST_OBJID', { classes: ['feature-objid'] }], - ['Status', 'Status', { fn: (v) => v === 1 ? 'Befintlig damm' : v === 2 ? 'Fd. damm' : '' }], - //['Regleringstyp', 'Regleringstyp'], - ['Byggår', 'ByggAr'], - ['Dammhöjd', 'DammHojd', { unit: 'm' }], - ['Krönlängd', 'KronLangd', { unit: 'm' }], - ['Fiskväg', 'Fiskvag', { fn: (v) => - v === 1 ? 'Bassängtrappa' : - v === 2 ? 'Denilränna' : - v === 3 ? 'Slitsränna' : - v === 4 ? 'Omlöp' : - v === 5 ? 'Inlöp' : - v === 6 ? 'Ålledare' : - v === 7 ? 'Smoltränna' : - v === 8 ? 'Okänd typ' : - v === 9 ? 'Ingen' : - v === 10 ? 'Annan' : - '' }], - ['Huvudavrinningsområdesnummer', 'HARO', { classes: ['feature-objid'] } ], - ['Vattendistrikt', 'Vattendistrikt', { classes: ['feature-objid'] } ], - ['Verksamhet', 'Verksamhet', { fn: (v) => - v === 1 ? 'Kraftproduktion' : - v === 2 ? 'Industri' : - v === 3 ? 'Sjöfart' : - v === 4 ? 'Invallning' : - v === 5 ? 'Vattenförsörjning' : - v === 6 ? 'Spegeldamm' : - v === 7 ? 'Historisk' : - v === 8 ? 'Övrigt' : - '' }], - ['Högsta dämningsgräns', 'DG', { unit: 'm' }], - ['Lägsta sänkningsgräns', 'SG', { unit: 'm' }], - ['Magasinsyta', 'MY', { unit: 'km²' }], - ['Reglerbar volym', 'RV', { unit: 'Mm³' }], - ['Kommentar', 'Kommentar'], - ], - legend: { zoomLevel: 5, type: 'point' }, - style: [2, 3, 4, 4, 4, 6, 8, 8, 8, 10, 16, 32].map(function(width) { - return new Style({ - zIndex: 59, - image: new CircleStyle({ - radius: width, - fill: new Fill({ - color: 'rgb(219, 30, 42)', - }), - stroke: new Stroke({ - width: Math.log2(width) * 2/5, - color: 'rgb(128, 17, 25)', - }), - }), - }); - }), - }, - - 'misc.gigafactories': { - popoverTitle: 'Stor industrisatsning', - popover: [ - ['Namn', 'Name'], - ['Länk', 'Url', { fn: function(v) { - if (v == null | v === '') { - return; - } - const a = document.createElement('a'); - a.href = v; - a.target = '_blank'; - const i = document.createElement('i'); - i.classList.add('bi', 'bi-box-arrow-up-right'); - a.appendChild(i); - return a; - }}], - ], - legend: { zoomLevel: 1, type: 'point' }, - style: [4, 6, 7, 8, 10, 12].map(function(width) { - return new Style({ - zIndex: 60, - image: new CircleStyle({ - radius: width, - fill: new Fill({ - color: 'rgb(152, 78, 163)', - }), - stroke: new Stroke({ - width: Math.log2(width) * 2/5, - color: 'rgb(119, 61, 128)', - }), - }), - }); - }) - .concat([1.5, 2, 2, 2, 2, 2].map(function(width) { - return new Style({ - zIndex: 58, - fill: new Fill({ - color: 'rgba(152, 78, 163, .4)', - }), - stroke: new Stroke({ - width: width, - color: 'rgb(119, 61, 128)', - }), - }); - })), - }, - - 'kskog.1' : { style: [ 56, 168, 0, .2] }, /* #1 Sannolikt kontinuitetsskog (preciserad) */ - 'kskog.2' : { style: [169, 0, 230, .2] }, /* #2 Sannolikt påverkad kontinuitetsskog (preciserad) */ - 'kskog.3' : { style: [152, 230, 0, .2] }, /* #3 Sannolikt kontinuitetsskog i fjällen (grövre precisering) */ - 'kskog.4' : { style: [ 76, 115, 0, .2] }, /* #4 Potentiell kontinuitetsskog (2015) */ -}; - const layerHierarchy = [ { text: 'Transmissionsnät för el', @@ -4132,11 +961,11 @@ const layerHierarchy = [ text: 'Skogsbruk', children: [ { - text: 'Uppförda (sedan 2000)', + text: 'Utförda avverkningar', layer: 'avverk.utford', }, { - text: 'Anmälda', + text: 'Avverkningsanmälningar', layer: 'avverk.anmald', }, ] @@ -4385,7 +1214,7 @@ const [mapLayers, featureOverlayLayer] = (function() { }); const isVisible = function(groupname) { return Object.keys(layers).some((layername) => - layername.startsWith(layername + '.') && styles[lyr] !== undefined); + layername.startsWith(groupname + '.') && styles[layername] !== undefined); }; const canWebGL2 = !!document.createElement('canvas').getContext('webgl2'); @@ -4393,6 +1222,7 @@ const [mapLayers, featureOverlayLayer] = (function() { * misc at the end so they show up on top of suface features */ const rasterLayers = ['kskog']; const vectorLayers = ['nv', 'mrr', 'skydd', 'ren', 'ri', 'avverk', 'vbk', 'svk', 'misc']; + const canFilterByAge = ['avverk', 'mrr', 'vbk']; /* layers for which features are dated */ const ret = {}; if (!canWebGL2) { @@ -4420,6 +1250,7 @@ const [mapLayers, featureOverlayLayer] = (function() { } vectorLayers.forEach(function(k) { + const canFilterByAge0 = canFilterByAge.includes(k); ret[k] = new VectorTileLayer({ source: new VectorTile({ url: baseurl + 'tiles/' + k + xyz, @@ -4435,7 +1266,22 @@ const [mapLayers, featureOverlayLayer] = (function() { declutter: false, visible: isVisible(k), style: function(feature, resolution) { - const style = styles[k + '.' + feature.getProperties().layer]; + /* WARN: very hot code path! */ + const properties = feature.getProperties(); + if (age_filter_settings.active) { + /* TODO avoid doing this checks for each feature; instead, set up a + * different style function if age_filter_settings.active */ + const ts = properties.ts; + if (ts == null) { + if (canFilterByAge0 && !age_filter_settings.show_unknown) { + return null; + } + } else if ((age_filter_settings._min_ts !== null && ts < age_filter_settings._min_ts) || + (age_filter_settings._max_ts !== null && ts > age_filter_settings._max_ts)) { + return null; + } + } + const style = styles[k + '.' + properties.layer]; if (!Array.isArray(style)) { return style; } else { @@ -4449,6 +1295,7 @@ const [mapLayers, featureOverlayLayer] = (function() { } }); ret[k].set('layerGroup', k, true); + ret[k].set('canFilterByAge', canFilterByAge0, true); map.addLayer(ret[k]); }); @@ -4686,11 +1533,8 @@ const infoMetadataAccordions = []; } Object.entries(result).forEach(function([lyr, visible]) { - const v = mapLayers[lyr]; - if (v != null) { - //console.log(lyr, visible); - v.setVisible(visible); - } + //console.log(lyr, visible); + mapLayers[lyr]?.setVisible(visible); }); const btn = document.getElementById('map-legend-button'); if (Object.values(styles).some((v) => v !== null)) { @@ -4702,17 +1546,14 @@ const infoMetadataAccordions = []; const onClickFunction = function(layerList, event) { featureOverlayLayer.setVisible(false); featureOverlayLayer.changed(); - const popover = Popover.getInstance(popup); - if (popover !== null) { - popover.dispose(); - } + Popover.getInstance(popup)?.dispose(); + const searchParams = new URLSearchParams(location.hash.substring(1)); let layersParams = searchParams.get('layers') || ''; layersParams = layersParams.match(/^\s*$/) ? [] : layersParams.split(' '); if (event.target.checked) { layerList.forEach(function(lyr) { - const l = mapLayers[lyr.split('.', 1)[0]]; - if (l == null) { + if (mapLayers[lyr.split('.', 1)[0]] == null) { return; /* keep unexisting layers (eg WebGL layers on a system without WebGL support) unselectable */ } styles[lyr] = layers[lyr].style; @@ -4920,413 +1761,474 @@ const infoMetadataAccordions = []; })(); })(); -/* popup and feature overlays */ +/* age filter panel */ (function() { - const popupOverlay = new Overlay({ - stopEvent: true, - element: popup, - }); - map.addOverlay(popupOverlay); + const panel = document.getElementById('age-filter-modal'); - let popover, overlayAttributes = [], overlayAttrIdx = 0; + const dialog_setup = (function() { + const dialog = document.createElement('div'); + dialog.classList.add('modal-dialog', 'modal-dialog-centered'); + panel.appendChild(dialog); - const header = document.createElement('div'); - header.classList.add('d-flex'); - - const headerGrabbingArea = document.createElement('div'); - headerGrabbingArea.classList.add('flex-grow-1', 'grabbing-area', 'pe-2', 'me-2'); - header.appendChild(headerGrabbingArea); - - headerGrabbingArea.onmousedown = function(event) { - if (event.button != 0) { - return; - } - const popoverTip = Popover.getInstance(popup).tip; - if (popoverTip.classList.contains('popover-maximized')) { - return; - } - pageNode.classList.add('grabbing-area-grabbed'); - - if (!popoverTip.classList.contains('popover-detached')) { - /* detach popover tip */ - popoverTip.classList.add('popover-detached'); - const rect = popoverTip.getBoundingClientRect(); - const maxHeight = document.getElementById('map').getBoundingClientRect().height - 1 - rect.top - - popoverTip.getElementsByClassName('popover-header')[0].getBoundingClientRect().height; - - const style = popoverTip.style; - style.display = 'none'; /* avoid reflows between the following assignments */ - style.position = 'absolute'; - style.transform = ''; - style.inset = `${rect.top}px auto auto ${rect.left}px`; - style.display = ''; - } - - let clientX = event.clientX, clientY = event.clientY; - document.onmousemove = function(event) { - const offsetX = clientX - event.clientX; - const offsetY = clientY - event.clientY; - clientX = event.clientX; - clientY = event.clientY; - popoverTip.style.top = (popoverTip.offsetTop - offsetY).toString() + 'px'; - popoverTip.style.left = (popoverTip.offsetLeft - offsetX).toString() + 'px'; - }; - - document.onmouseup = function(event) { - if (event.button != 0) { - return; - } - pageNode.classList.remove('grabbing-area-grabbed'); - document.onmousemove = null; - document.onmouseup = null; - }; - }; - - const pageNode = document.createElement('h6'); - headerGrabbingArea.appendChild(pageNode); - - const pageNum = document.createElement('span'); - const pageCount = document.createElement('span'); - pageNode.appendChild(document.createTextNode('Träff ')); - pageNode.appendChild(pageNum); - pageNode.appendChild(document.createTextNode(' av ')); - pageNode.appendChild(pageCount); + const content = document.createElement('div'); + content.classList.add('modal-content'); + dialog.appendChild(content); - const featureOverlayStyle = new Style({ - stroke: new Stroke({ - color: 'rgba(0, 255, 255, .8)', - width: 3, - }), - }); - const updateFeatureOverlayLayer = function(layer_group, layer, id) { - const lyr = mapLayers[layer_group]; - if (lyr == null) { - return; - } - const urls = lyr.getSource().getUrls(); - const source = featureOverlayLayer.getSource(); - if (source.getUrls().length < 1 || source.getUrls()[0] !== urls[0]) { - featureOverlayLayer.setVisible(false); - source.setUrls(urls); - } - featureOverlayLayer.setStyle(function(feature, resolution) { - if (feature.getId() === id && feature.getProperties().layer === layer) { - return featureOverlayStyle; - } else { - return undefined; + const header = document.createElement('div'); + header.classList.add('modal-header'); + content.appendChild(header); + + const title = document.createElement('div'); + title.classList.add('h4', 'm-0'); + header.appendChild(title); + title.innerHTML = 'Filtrera objekt efter ålder'; + + const btn_close = document.createElement('button'); + btn_close.classList.add('btn-close'); + btn_close.type = 'button'; + btn_close.title = 'Stäng'; + btn_close.setAttribute('aria-label', btn_close.title); + btn_close.setAttribute('data-bs-dismiss', 'modal'); + header.appendChild(btn_close); + + const body = document.createElement('div'); + body.classList.add('modal-body'); + content.appendChild(body); + + const p = document.createElement('p'); + p.classList.add('small', 'text-muted', 'age-filter-infotext'); + body.appendChild(p); + p.appendChild(document.createTextNode('Här kan du t.ex. filtrera bort gamla objekt. ' + + 'I nulaget gäller filtret endast objekt inom ')); + ['mineralrättigheter', 'skogsbruk', 'vindbruk'].forEach(function(l, idx, arr) { + if (idx > 0) { + p.appendChild(document.createTextNode(idx < arr.length-1 ? ', ' : ' eller ')); } + const i = document.createElement('i'); + i.innerHTML = l; + p.appendChild(i); + }); + p.appendChild(document.createTextNode(' skikter.')); + + const form = document.createElement('form'); + form.action = '#'; + form.id = 'age-filter-form'; + body.appendChild(form); + + const btn_group = document.createElement('div'); + btn_group.classList.add('btn-group'); + btn_group.setAttribute('role', 'group'); + btn_group.setAttribute('aria-label', 'Välj filtreringstyp'); + form.appendChild(btn_group); + + const type_choices = Object.fromEntries([ + { id: 'relative', text: 'Åldersgräns', desc: 'som är' }, + { id: 'interval', text: 'Datumintervall', desc: 'med datum' }, + ].map(function(x) { + const radio = document.createElement('input'); + radio.classList.add('btn-check'); + radio.type = 'radio'; + radio.name = 'age-filter-type'; + radio.id = 'age-filter-type-' + x.id; + radio.required = true; + radio.setAttribute('aria-expanded', 'false'); + radio.setAttribute('autocomplete', 'off'); + btn_group.appendChild(radio); + + const lbl = document.createElement('label'); + lbl.classList.add('btn', 'btn-primary'); + lbl.setAttribute('for', radio.id); + lbl.appendChild(document.createTextNode(x.text)); + btn_group.appendChild(lbl); + + const div = document.createElement('div'); + div.classList.add('d-none', 'age-filter-settings'); + div.setAttribute('aria-hidden', 'true'); + form.appendChild(div); + + const p = document.createElement('p'); + p.classList.add('age-filter-settings-desc'); + div.appendChild(p); + const t = document.createTextNode('Visa endast objekt ' + x.desc + ':'); + p.appendChild(t); + + return [x.id, { radio: radio, div: div } ]; + })); + + Object.values(type_choices).forEach(function(type_choice) { + type_choice.radio.onclick = function(event) { + const radio = event.target; + radio.checked = true; + radio.setAttribute('aria-expanded', 'true'); + + Object.values(type_choices).forEach(function(x) { + const isSame = radio.isEqualNode(x.radio); + if (isSame) { + x.div.classList.remove('d-none'); + x.div.setAttribute('aria-hidden', 'false'); + } else { + x.div.classList.add('d-none'); + x.div.setAttribute('aria-hidden', 'true'); + x.radio.checked = false; + x.radio.setAttribute('aria-expanded', 'false'); + } + const inputs = x.div.getElementsByTagName('input'); + for (let i = 0; i < inputs.length; i++) { + inputs[i].required = isSame; + } + }); + }; }); - featureOverlayLayer.setVisible(true); - featureOverlayLayer.changed(); - }; - const refreshPopover = function() { - const attr = overlayAttributes[overlayAttrIdx]; - updateFeatureOverlayLayer(attr.layer_group, attr.layer, attr.ogc_fid); - - pageNum.innerHTML = (overlayAttrIdx + 1).toString(); - const content = formatFeaturePropertiesToHTML(attr); - popover.tip.getElementsByClassName('popover-body')[0].replaceChildren(content); - }; - const onClickPageChange = function(event, offset) { - const btn = event.target; - if (btn.classList.contains('disabled') || popover === null || popover.tip === null) { - return; - } - if (overlayAttrIdx + offset < 0 || overlayAttrIdx + offset > overlayAttributes.length - 1) { - return; - } - - overlayAttrIdx += offset; - if (overlayAttrIdx < 1) { - btnPrev.classList.add('disabled'); - } else { - btnPrev.classList.remove('disabled'); - } - if (overlayAttrIdx < overlayAttributes.length - 1) { - btnNext.classList.remove('disabled'); - } else { - btnNext.classList.add('disabled'); - } - refreshPopover(); - setTimeout(function() { btn.blur() }, 100); - }; + const create_select = function(parentNode, select_label, options) { + const select = document.createElement('select'); + select.classList.add('form-select'); + select.setAttribute('aria-label', select_label); + parentNode.appendChild(select); + return [ + select, + Object.fromEntries(options.map(function(x) { + const option = document.createElement('option'); + option.appendChild(document.createTextNode(x.text)); + option.value = x.id; + select.appendChild(option); + return [x.id, option]; + })) + ]; + }; - const btnPrev = document.createElement('button'); - btnPrev.classList.add('popover-button', 'popover-button-prev'); - btnPrev.setAttribute('type', 'button'); - btnPrev.title = 'Föregående träff'; - btnPrev.setAttribute('aria-label', btnPrev.title); - btnPrev.onclick = function(event) { - return onClickPageChange(event, -1); - }; + const format_date = function(d, s) { /* YYYY-MM-DD or YYYYMMDD */ + return d.getFullYear() .toString().padStart(4, '0') + (s ?? '-') + + (d.getMonth()+1).toString().padStart(2, '0') + (s ?? '-') + + d.getDate() .toString().padStart(2, '0'); + }; + const parse_date = (m) => new Date( /* YYYY-MM-DD */ + parseInt(m.slice(0,4), 10), + parseInt(m.slice(5,7), 10)-1, + parseInt(m.slice(8,10),10), + 12 /* use 12:00:00.0 like for URL parameters */ + ); + + (function(type_choice) { + const div = document.createElement('div'); + div.classList.add('input-group'); + type_choice.div.appendChild(div); + + type_choice.operator = create_select(div, 'Under eller över åldersgränsen', [ + { id: '<=', text: 'Nyare' }, + { id: '>=', text: 'Äldre' }, + ]); + + const span = document.createElement('span'); + span.classList.add('input-group-text'); + div.appendChild(span); + span.innerHTML = 'än'; + + const input_quantity = type_choice.quantity = document.createElement('input'); + input_quantity.classList.add('form-control'); + input_quantity.type = 'number'; + input_quantity.min = 0; + input_quantity.max = 65535; + input_quantity.placeholder = 'Antal'; + input_quantity.setAttribute('aria-label', input_quantity.placeholder); + div.appendChild(input_quantity); + + type_choice.unit = create_select(div, 'Enhet', [ + { id: 'd', text: 'dagar' }, + { id: 'w', text: 'veckor' }, + { id: 'm', text: 'månader' }, + { id: 'y', text: 'år' }, + ]); + + const p = document.createElement('p'); + p.classList.add('small', 'text-muted', 'invisible'); + type_choice.div.appendChild(p); + p.appendChild(document.createTextNode('Det vill säga med datum ')); + const span_date = document.createElement('span'); + p.appendChild(span_date); + p.appendChild(document.createTextNode(' eller ')); + const span_direction = document.createElement('span'); + p.appendChild(span_direction); + p.appendChild(document.createTextNode('.')); + + type_choice._update_helptext = function() { + const d = age_filter_settings.get_relative_date( + parseInt(type_choice.quantity.value, 10), + type_choice.unit[0].value + ); + const operator = type_choice.operator[0].value; + if (d == null || operator === '') { + p.classList.add('invisible'); + return null; + } else { + /* update help text */ + /* TODO auto update the date passed midnight (if the modal is open) */ + span_date.innerHTML = format_date(d); + span_direction.innerHTML = { '>=':'tidigare', '<=':'senare' }[operator]; + p.classList.remove('invisible'); + return d; + } + }; - const btnNext = document.createElement('button'); - btnNext.classList.add('popover-button', 'popover-button-next'); - btnNext.setAttribute('type', 'button'); - btnNext.title = 'Nästa träff'; - btnNext.setAttribute('aria-label', btnNext.title); - btnNext.onclick = function(event) { - return onClickPageChange(event, +1); - }; + type_choice.operator[0].onchange = input_quantity.onchange + = type_choice.unit[0].onchange + = function() { + const d = type_choice._update_helptext(); + if (d != null) { + /* propagate to interval tab */ + const operator = type_choice.operator[0].value; + const [d1, d2] = { '>=': [new Date(1900, 0, 1, 12), d], /* between 1900-01-01 and d */ + '<=': [d, new Date()], /* between d and today */ + }[operator]; + type_choices.interval.from.value = format_date(d1); + type_choices.interval.to.value = format_date(d2); + } + }; + })(type_choices.relative); - const btnExpand = document.createElement('button'); - btnExpand.classList.add('popover-button', 'popover-button-expand'); - btnExpand.setAttribute('type', 'button'); - const btnExpandTitle = 'Förstora'; - const btnExpandTitle2 = 'Förminska'; - btnExpand.setAttribute('aria-label', btnExpand.title); - btnExpand.onclick = function(event) { - if (popover === null || popover.tip === null) { - return; - } - if (!popover.tip.classList.contains('popover-maximized')) { - popover.tip.classList.add('popover-maximized'); - btnExpand.classList.replace('popover-button-expand', 'popover-button-reduce'); - btnExpand.title = btnExpandTitle2; - btnExpand.setAttribute('aria-label', btnExpand.title); - } else { - popover.tip.classList.remove('popover-maximized'); - btnExpand.classList.replace('popover-button-reduce', 'popover-button-expand'); - btnExpand.title = btnExpandTitle; - btnExpand.setAttribute('aria-label', btnExpand.title); - } - setTimeout(function() { btnExpand.blur() }, 100); - }; + (function(type_choice) { + const div = document.createElement('div'); + div.classList.add('input-group'); + type_choice.div.appendChild(div); + + const span1 = document.createElement('span'); + span1.classList.add('input-group-text'); + span1.innerHTML = 'Mellan'; + span1.id = 'age-filter-interval-from'; + div.appendChild(span1); + + const date1 = type_choice.from = document.createElement('input'); + date1.classList.add('form-control'); + date1.type = 'date'; + date1.setAttribute('aria-label', 'Intervallstart'); + date1.setAttribute('aria-describedby', span1.id); + div.appendChild(date1); + + const span2 = document.createElement('span'); + span2.classList.add('input-group-text'); + span2.innerHTML = 'och'; + span2.id = 'age-filter-interval-to'; + div.appendChild(span2); + + const date2 = type_choice.to = document.createElement('input'); + date2.classList.add('form-control'); + date2.type = 'date'; + date2.setAttribute('aria-label', 'Intervallstop'); + date2.setAttribute('aria-describedby', span2.id); + div.appendChild(date2); + + /* propagate to relative tab by trying to preserve the operator and unit */ + const propagate_to_relative = function() { + let d; + switch (type_choices.relative.operator[0].value) { + case '<=': + d = parse_date(date1.value); + break; + case '>=': + d = parse_date(date2.value); + break; + } + const delta = (new Date().getTime() - d.getTime()) / 86_400_000; + let v; + switch (type_choices.relative.unit[0].value) { + case 'd': + v = delta; + break; + case 'w': + v = delta/7; + break; + case 'm': + v = delta*12/365.25; + break; + case 'y': + v = delta/365.25; + break; + } + if (v != null) { + type_choices.relative.quantity.value = Math.round(v); + type_choices.relative._update_helptext(); + } + }; - const btnClose = document.createElement('button'); - btnClose.classList.add('popover-button', 'popover-button-close'); - btnClose.setAttribute('type', 'button'); - btnClose.title = 'Stäng'; - btnClose.setAttribute('aria-label', btnClose.title); - btnClose.onclick = function(event) { - featureOverlayLayer.setVisible(false); - featureOverlayLayer.changed(); - if (popover !== null) { - popover.dispose(); - } - }; + /* make sure that from_date ≤ to_date */ + date1.onchange = function() { + if (date1.value !== '' && (date2.value === '' || date1.value > date2.value)) { + date2.value = date1.value; + } + propagate_to_relative(); + }; + date2.onchange = function() { + if (date2.value !== '' && (date1.value === '' || date1.value > date2.value)) { + date1.value = date2.value; + } + propagate_to_relative(); + }; + })(type_choices.interval); - header.appendChild(btnPrev); - header.appendChild(btnNext); - header.appendChild(btnExpand); - header.appendChild(btnClose); + const show_unknown_age = (function() { + const div = document.createElement('div'); + div.classList.add('form-check', 'form-switch'); + form.appendChild(div); + + const checkbox = document.createElement('input'); + checkbox.classList.add('form-check-input'); + checkbox.type = 'checkbox'; + checkbox.id = 'age-filter-show-unknown'; + checkbox.setAttribute('role', 'switch'); + checkbox.checked = age_filter_settings.show_unknown; + div.appendChild(checkbox); + + const lbl = document.createElement('label'); + lbl.classList.add('form-check-label'); + lbl.setAttribute('for', checkbox.id); + lbl.innerHTML = 'Visa även objekt med okänd datum.'; + div.appendChild(lbl); + + return checkbox; + })(); + + const footer = document.createElement('div'); + footer.classList.add('modal-footer'); + content.appendChild(footer); + + const btn_cancel = document.createElement('button'); + btn_cancel.classList.add('btn', 'btn-secondary'); + btn_cancel.type = 'button'; + btn_cancel.innerHTML = 'Återställ'; + footer.appendChild(btn_cancel); + + const btn_apply = document.createElement('input'); + btn_apply.classList.add('btn', 'btn-primary'); + btn_apply.type = 'submit'; + btn_apply.value = 'Filter'; + btn_apply.setAttribute('form', form.id); + footer.appendChild(btn_apply); + + btn_cancel.onclick = function() { + /* deactivate deactivate the filter but preserve its settings */ + age_filter_settings.active = false; + Object.values(mapLayers).forEach(function(lyr) { + if (lyr?.get('canFilterByAge')) { + lyr.changed(); + } + }); - const formatFeaturePropertiesToHTML = function(properties) { - /* turn the properties into a fine table */ - const table = document.createElement('table'); - table.classList.add('table', 'table-sm', 'table-borderless', 'table-hover'); + const params = new URLSearchParams(window.location.hash.substring(1)); + params.delete('age-filter'); + params.delete('show-unknown-age'); + location.hash = '#' + params.toString(); - const tbody = document.createElement('tbody'); - table.appendChild(tbody); + modal.hide(); + }; - const def = layers[properties.layer_group + '.' + properties.layer]; - def.popover.forEach(function([desc, key, opts]) { - let v = properties[key]; - if (opts === undefined) { - opts = {}; - } - if (opts.fn !== undefined) { - if (opts.fn === 'length') { - if (v < 1000) { - opts.unit = 'm'; - } else { - v /= 1000.; - v = Math.round(v*100) / 100.; - opts.unit = 'km'; - } - } else if (opts.fn === 'area') { - if (v < 10000) { - opts.unit = 'm²'; - } else if (v < 10000 * 10000) { - v /= 10000.; - opts.unit = 'ha'; - } else { - v /= 1000000.; - opts.unit = 'km²'; - } - v = Math.round(v*100) / 100.; - } else { - v = opts.fn(v); - } - } - if (v == null) { - v = document.createTextNode(''); - } else if (!(v instanceof HTMLElement)) { - if (typeof(v) === 'number' && opts.unit !== undefined) { - v = v.toLocaleString('sv-SE'); - } else if (typeof(v) === 'boolean') { - v = v ? 'Ja' : 'Nej'; + form.onsubmit = function(event) { + event.preventDefault(); + const [filter_type, filter_settings] = Object.entries(type_choices).filter( (x) => x[1].radio.checked )[0]; + let param; + age_filter_settings._min_ts = age_filter_settings._max_ts = null; + switch (filter_type) { + case 'relative': { + const operator = age_filter_settings.operator = filter_settings.operator[0].value; + age_filter_settings.quantity = parseInt(filter_settings.quantity.value, 10); + age_filter_settings.unit = filter_settings.unit[0].value; + param = {'<=':'-', '>=':''}[operator]; + param += age_filter_settings.quantity.toString() + age_filter_settings.unit; + break; } - if (opts.unit !== undefined && v !== '') { - v += '\u202F' + opts.unit; + case 'interval': { + const date1 = age_filter_settings.from = parse_date(filter_settings.from.value); + const date2 = age_filter_settings.to = parse_date(filter_settings.to.value); + param = format_date(date1, '') + '-' + format_date(date2, ''); + break; } - v = document.createTextNode(v); + default: + return; } + age_filter_settings.type = filter_type; + age_filter_settings.show_unknown = show_unknown_age.checked; + age_filter_settings.setup_minmax(); + age_filter_settings.active = true; + /* TODO auto update the filter passed midnight (if active) */ + Object.values(mapLayers).forEach(function(lyr) { + if (lyr?.get('canFilterByAge')) { + lyr.changed(); + } + }); - const tr = document.createElement('tr'); - tbody.appendChild(tr); + const params = new URLSearchParams(window.location.hash.substring(1)); + params.set('age-filter', param); + params.set('show-unknown-age', show_unknown_age.checked ? '1' : '0'); + location.hash = '#' + params.toString(); - const td1 = document.createElement('td'); - tr.appendChild(td1); - const textDesc = document.createTextNode(desc); - td1.appendChild(textDesc); + modal.hide(); + }; - const td2 = document.createElement('td'); - tr.appendChild(td2); - td2.appendChild(v); - if (opts.classes !== undefined) { - opts.classes.forEach((c) => td2.classList.add(c)); + /* Now that all elements have been added to the form, click the radio + * button to show the relevant <div>, mark its fields as required and + * fills them. The function is run whenever the modal is shown. */ + return function() { + const type_choice = type_choices[age_filter_settings.type]; + type_choice.radio.click(); + + switch (age_filter_settings.type) { + case 'relative': { + Object.entries(type_choice.operator[1]).map(function([id, option]) { + option.selected = id === age_filter_settings.operator; + }); + type_choice.quantity.value = age_filter_settings.quantity.toString(); + Object.entries(type_choice.unit[1]).map(function([id, option]) { + option.selected = id === age_filter_settings.unit; + }); + type_choice.quantity.dispatchEvent(new Event('change')); /* propagate to absolute */ + break; + } + case 'interval': { + type_choice.from.value = format_date(age_filter_settings.from); + type_choice.to.value = format_date(age_filter_settings.to); + type_choice.from.dispatchEvent(new Event('change')); /* propagate to relative */ + break; + } } - }); + }; + })(); - const content = document.createElement('div'); - if (def.popoverTitle !== undefined) { - const h = document.createElement('h6'); - content.appendChild(h); - const textNode = document.createTextNode(def.popoverTitle); - h.appendChild(textNode); - } + const modal = new Modal(panel, { + backdrop: false, + }); - content.appendChild(table); - return content; + const backdrop = document.getElementById('age-filter-modal-backdrop'); + backdrop.onclick = function() { + modal.hide(); }; - const container0 = map.getViewport().getElementsByClassName('ol-overlaycontainer-stopevent')[0]; - map.on('singleclick', function(event) { - /* clear the overlay list */ - featureOverlayLayer.setVisible(false); - featureOverlayLayer.changed(); - overlayAttributes = []; - overlayAttrIdx = 0; - - /* dispose any pre-existing popover if not in detached mode */ - popover = Popover.getInstance(popup); - if (popover !== null) { - const popoverTip = popover.tip; - if (popoverTip !== null && !popoverTip.classList.contains('popover-detached')) { - popover.dispose(); - } - } - - const size = map.getSize(); - if (size[0] < 576 || size[1] < 576) { - return; - } - - /* unclear how many feature we'll find, don't render prev/next buttons for now */ - pageNode.classList.add('d-none'); - btnPrev.classList.add('d-none', 'disabled'); - btnNext.classList.add('d-none', 'disabled'); - - /* never start in maximized mode */ - if (popover !== null && popover.tip !== null) { - popover.tip.classList.remove('popover-maximized'); + const btn = document.getElementById('age-filter-button').getElementsByTagName('button')[0]; + if (age_filter_settings.active) { + btn.classList.replace('btn-light', 'btn-dark'); + } + panel.addEventListener('show.bs.modal', function() { + backdrop.classList.add('modal-backdrop', 'show'); + btn.setAttribute('aria-expanded', 'true'); + btn.classList.replace('btn-light', 'btn-dark'); + }); + panel.addEventListener('hide.bs.modal', function() { + /* XXX workaround for https://github.com/twbs/bootstrap/issues/41005#issuecomment-2585390544 */ + const activeElement = document.activeElement; + if (activeElement instanceof HTMLElement) { + activeElement.blur(); } - btnExpand.classList.replace('popover-button-reduce', 'popover-button-expand'); - btnExpand.title = btnExpandTitle; - btnExpand.setAttribute('aria-label', btnExpand.title); - - const fetch_body = [] - map.forEachFeatureAtPixel(event.pixel, function(feature, layer) { - const layerGroup = layer.get('layerGroup'); - const layerName = feature.getProperties().layer; - const def = layers[layerGroup + '.' + layerName]; - if (def !== undefined && def.popover !== undefined) { - /* skip layers which didn't opt-in for popover */ - if (!fetch_body.length) { - document.body.classList.add('inprogress'); - if (popover !== null && popover.tip !== null) { - popover.tip.classList.add('inprogress'); - } - } - fetch_body.push({ - layer_group: layerGroup, - layer: layerName, - fid: feature.getId() ?? -1, - }); - if (fetch_body.length >= 100) { - return true; /* enough matches already, stop detection here */ - } - } - }, { - hitTolerance: 5, - checkWrapped: false, - layerFilter: (l) => l.get('layerGroup') != null, - }); - - if (fetch_body.length === 0) { - if (popover !== null) { - /* dispose pre-detached popover */ - popover.dispose(); - } - return; + }); + panel.addEventListener('hidden.bs.modal', function() { + if (!age_filter_settings.active) { + btn.classList.replace('btn-dark', 'btn-light'); } + btn.setAttribute('aria-expanded', 'false'); + backdrop.classList.remove('modal-backdrop', 'show'); + }); - fetch('/q', { - method: 'POST', - body: JSON.stringify(fetch_body), - headers: { - 'Content-Type': 'application/json; charset=UTF-8' - } - }) - .then(function(resp) { - if (resp.status === 200) { - return resp.json(); - } else { - throw new Error(`${resp.url} [${resp.status}]`); - } - }) - .then(function(data) { - /* the data is received from the CGI in the order it was sent */ - /* TODO optimizations on the CGI would break the above assumption, so the - * decoded JSON response would need to be reordered to match fetch_body */ - overlayAttributes = data - if (overlayAttributes.length === 0) { - if (popover !== null) { - /* dispose pre-detached popover */ - popover.dispose(); - } - return; - } + btn.onclick = function() { + dialog_setup(); + modal.show(); + }; +})(); - pageCount.innerHTML = overlayAttributes.length.toString(); - if (overlayAttributes.length >= 2) { - /* render prev/pre buttons */ - btnNext.classList.remove('d-none', 'disabled'); - btnPrev.classList.remove('d-none'); - pageNode.classList.remove('d-none'); - } - if (popover === null || popover.tip === null) { - /* create a new popover (we're not already showing one in detached mode) */ - pageNum.innerHTML = (overlayAttrIdx + 1).toString(); - popupOverlay.setPosition(event.coordinate); - - const attr = overlayAttributes[0]; - updateFeatureOverlayLayer(attr.layer_group, attr.layer, attr.ogc_fid); - popover = new Popover(popup, { - template: '<div class="popover" role="tooltip"><div class="popover-arrow"></div>' + - '<div class="popover-header"></div><div class="popover-body"></div></div>', - title: header, - content: formatFeaturePropertiesToHTML(attr), - html: true, - placement: 'right', - fallbackPlacements: ['right', 'left', 'bottom', 'top'], - container: container0, - }); - popover.show(); - } - else if (popover.tip.classList.contains('popover-detached')) { - /* update existing detached mode popover */ - refreshPopover(); - popover.tip.classList.remove('inprogress'); - } - }) - .catch(function(e) { - console.log(e); - }) - .finally(function() { - document.body.classList.remove('inprogress'); - }); - }); -}()); +popover(map, mapLayers, featureOverlayLayer); |