aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--index.html73
-rw-r--r--main.js229
-rw-r--r--style.css61
3 files changed, 310 insertions, 53 deletions
diff --git a/index.html b/index.html
index 4b4804e..e9c330b 100644
--- a/index.html
+++ b/index.html
@@ -21,58 +21,31 @@
<h5 class="my-0">Källor och licensinformation</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" title="Stäng" aria-label="Stäng"></button>
</div>
- <div class="modal-body pt-2">
- <ul class="mb-2">
- <li><i>Transmissionsnät för el</i> från
- <a href="https://svk.se" target="_blank">Svenska Kraftnät (SvK)</a>.
- </li>
- <li><i>Dammregistret</i> från
- <a href="https://smhi.se" target="_blank">Sveriges meteorologiska och hydrologiska institut (SMHI)</a>,
- CC-BY-4.0 (<a href="https://www.smhi.se/data/oppna-data/villkor-for-anvandning-1.30622" target="_blank">öppna data</a>).
- </li>
- <li><i>Mineralrättsregistret</i> från
- <a href="https://www.sgu.se/bergsstaten/" target="_blank">Bergsstaten</a>,
- CC0 (<a href="https://creativecommons.org/publicdomain/zero/1.0/deed.sv" target="_blank">öppna data</a>).
- </li>
- <li><i>Vindbruk</i> från
- <a href="https://www.energimyndigheten.se/energisystem-och-analys/elproduktion/vindkraft/vindbrukskollen/" target="_blank">Länsstyrelserna och Energimyndigheten</a>,
- CC0 (<a href="https://ext-geodatakatalog-forv.lansstyrelsen.se/GeodataKatalogen/codelist/metadata/anvandningsrestriktioner.xml#CC01.0" target="_blank">öppna data</a>).
- </li>
- <li><i>Skogsbruk</i>, <i>Skogliga biotopskyddsområden</i> och <i>Naturvårdsavtal</i> från
- <a href="https://skogsstyrelsen.se" target="_blank">Skogsstyrelsen</a>,
- CC0 (<a href="https://www.skogsstyrelsen.se/sjalvservice/karttjanster/geodatatjanster/villkor-for-nyttjande-av-skogsstyrelsens-kartdatabaser/" target="_blank">öppna data</a>).
- </li>
- <li><i>Naturvårdsregistret</i> och <i>Naturvårdsavtal</i> från
- <a href="https://www.naturvardsverket.se/" target="_blank">Naturvårdsverket</a>,
- CC0 (<a href="https://geodata.naturvardsverket.se/nedladdning/naturvardsregistret/Naturvardsregistret_beskrivning_av_oppna_data.pdf" target="_blank">öppna data</a>).
- </li>
- <li><i>Riksintresse naturvård</i> och <i>frilufsliv</i> från
- <a href="https://www.naturvardsverket.se/" target="_blank">Naturvårdsverket</a>
- och
- <a href="https://www.lansstyrelsen.se/" target="_blank">Länsstyrelsen</a>,
- CC-BY-4.0 (<a href="https://ext-geodatakatalog-forv.lansstyrelsen.se/GeodataKatalogen/codelist/metadata/anvandningsrestriktioner.xml#CCby4.0" target="_blank">öppna data</a>).
- </li>
- <li><i>Riksintresse Rennäringen</i> skikt från
- <a href="https://sametinget.se" target="_blank">Sametinget</a>,
- CC-BY-4.0 (<a href="https://ext-geodatakatalog-forv.lansstyrelsen.se/GeodataKatalogen/codelist/metadata/anvandningsrestriktioner.xml#CCby4.0" target="_blank">öppna data</a>).
- <i>Samebyarnas betesområden</i> och <i>flyttled</i> från
- &copy; <a href="https://sametinget.se" target="_blank">Sametingets</a>
- Rennäringens markanvändningsdatabas (IRENMARK).
- </li>
- <li>Bakgrund kartor från
- &copy; <a href="https://lantmateriet.se" target="_blank">Lantmäteriet</a>, CC0
- (<a href="https://www.lantmateriet.se/sv/geodata/vara-produkter/oppna-data/#anchor-1" target="_blank">öppna data</a>).
- </li>
- <li>Webbkartan:
- &copy; <a href="https://guilhem.se" target="_blank">Guilhem Moulin</a>, AGPLv3+.
- <a href="https://git.guilhem.org/KlimatanalysNorr/webmap" target="_blank">Källkod</a>.
- </li>
- <li>Backend-verktyg:
- &copy; <a href="https://guilhem.se" target="_blank">Guilhem Moulin</a>, GPLv3+.
- <a href="https://git.guilhem.org/KlimatanalysNorr/tools" target="_blank">Källkod</a>.
+ <div id="info-body" class="modal-body">
+ <ul class="list-group list-group-flush mb-2">
+ <li class="list-group-item">
+ <h6>Bakgrund kartor</h6>
+ <p>&copy; <a href="https://lantmateriet.se" target="_blank">Lantmäteriet</a></p>
+ <p>Licensvillkor: <a href="https://www.lantmateriet.se/sv/geodata/vara-produkter/oppna-data/#anchor-1" target="_blank">CC0 1.0 Universiell</a></p>
+ </li>
+ <li class="list-group-item">
+ <h6>Webbkartan</h6>
+ <p>&copy; Guilhem Moulin</p>
+ <p>Licensvillkor: <a href="https://www.gnu.org/licenses/agpl-3.0.en.html" target="_blank">AGPLv3+</a></p>
+ <p class="small text-muted"><i class="bi bi-file-earmark-code"></i>
+ <a href="https://git.guilhem.org/KlimatanalysNorr/webmap" target="_blank">Källkod <i class="bi bi-box-arrow-up-right"></i></a></p>
+ </li>
+ <li class="list-group-item">
+ <h6>Backend verktyg</h6>
+ <p>&copy; Guilhem Moulin</p>
+ <p>Licensvillkor: <a href="https://www.gnu.org/licenses/gpl-3.0.en.html" target="_blank">GPLv3+</a> och
+ (endast CGI) <a href="https://www.gnu.org/licenses/agpl-3.0.en.html" target="_blank">AGPLv3+</a></p>
+ <p class="small text-muted"><i class="bi bi-file-earmark-code"></i>
+ <a href="https://git.guilhem.org/KlimatanalysNorr/tools" target="_blank">Källkod <i class="bi bi-box-arrow-up-right"></i></a></p>
</li>
</ul>
- <p class="small mb-0">Webbkartan är utvecklad av
+ <div id="info-accordion" class="accordion accordion-flush"></div>
+ <p class="small text-muted info-credits">Webbkartan är utvecklad av
<a href="https://guilhem.se" target="_blank">Guilhem Datakonsult</a> på uppdrag av
<a href="https://www.klimatanalysnorr.se" target="_blank">Klimatanalys Norr projektet</a>.</p>
</div>
diff --git a/main.js b/main.js
index 6808456..17ca1cc 100644
--- a/main.js
+++ b/main.js
@@ -483,10 +483,189 @@ if (window.location === window.parent.location) {
btn.classList.replace('btn-dark', 'btn-light');
btn.setAttribute('aria-expanded', 'false');
backdrop.classList.remove('modal-backdrop', 'show');
+ infoMetadataAccordions.forEach(function(x, idx) {
+ /* collapse all accordions */
+ const body = x.element.parentNode.parentNode;
+ const name = 'info-accordion-collapse-' + idx;
+ if (body.id === name) {
+ body.classList.remove('show');
+ }
+ if (body.parentNode !== null) {
+ const headers = body.parentNode.getElementsByClassName('accordion-header');
+ for (let i = 0; i < headers.length; i++) {
+ const buttons = headers[i].getElementsByClassName('accordion-button');
+ for (let j = 0; j < buttons.length; j++) {
+ const btn = buttons[j];
+ if (btn.getAttribute('data-bs-target') === '#' + name) {
+ btn.setAttribute('aria-expanded', 'false');
+ btn.classList.add('collapsed');
+ }
+ }
+ }
+ }
+ });
});
btn.onclick = function(event) {
- modal.toggle();
+ infoMetadataAccordions.forEach((x) => x.element.replaceChildren());
+ modal.show();
+ Promise.allSettled(Object.entries(vectorLayers).map(function([grp,lyr]) {
+ const url = lyr.getSource().getUrls()[0];
+ if (url === undefined || url.length <= 16 || url.substr(url.length - 16) !== '/{z}/{x}/{y}.pbf') {
+ throw new Error(`Invalid URL ${url}`);
+ }
+ return fetch(url.substr(0, url.length - 16) + '/metadata.json')
+ .then(function(resp0) {
+ if (resp0.status === 200) {
+ return resp0.json().then((x) => [grp,x]);
+ } else {
+ throw new Error(`${resp0.url} [${resp0.status}]`);
+ }
+ });
+ }))
+ .then(function(rs) {
+ const metadata = Object.fromEntries(rs.filter(function(r) {
+ if (r.status === 'fulfilled') {
+ return true;
+ } else if (r.status === 'rejected') {
+ console.log(r.reason);
+ }
+ return false;
+ }).map((r) => r.value));
+
+ infoMetadataAccordions.forEach(function(x) {
+ const ul = x.element;
+ const groupnames = new Set();
+ const last_updated = [];
+ x.items.forEach(function([groupname, _]) {
+ const layer_group = metadata[groupname];
+ if (layer_group === undefined) {
+ return;
+ }
+ if (!groupnames.has(groupname)) {
+ groupnames.add(groupname);
+ if (layer_group.last_updated !== undefined) {
+ last_updated.push(layer_group.last_updated);
+ }
+ }
+ });
+ if (last_updated.length > 0) {
+ /* show creation time of the MVT layers */
+ const li = document.createElement('li');
+ li.classList.add('list-group-item', 'text-muted');
+ ul.appendChild(li)
+ const i = document.createElement('i');
+ i.classList.add('bi', 'bi-clock');
+ li.appendChild(i);
+ const t = document.createTextNode(
+ ' Lokalt skikt (vectiler) genererades ' +
+ last_updated
+ .sort()
+ .map((ts) => new Date(ts).toLocaleDateString('sv-SE'))
+ .join('; ') + '.'
+ );
+ li.appendChild(t);
+ }
+
+ const source_files = new Set();
+ 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 === undefined || layer_group.layers === undefined || layer_group.source_files === undefined) {
+ return;
+ }
+ const def = layer_group.layers[layername];
+ if (def === undefined || def.source_files === undefined) {
+ return;
+ }
+ def.source_files.forEach(function(source_file) {
+ if (source_files.has(source_file)) {
+ return;
+ }
+ const x = layer_group.source_files[source_file];
+ source_files.add(source_file);
+
+ const li = document.createElement('li');
+ li.classList.add('list-group-item');
+ ul.appendChild(li)
+ const h = document.createElement('h6');
+ li.appendChild(h)
+ if (x.description !== undefined && x.description !== null) {
+ const t = document.createTextNode(x.description);
+ h.appendChild(t);
+ }
+
+ if (x.copyright !== undefined && x.copyright !== null) {
+ let p = document.createElement('p');
+ li.appendChild(p)
+ const t = document.createTextNode(x.copyright);
+ p.appendChild(t);
+ }
+
+ if (x.license !== undefined && x.license !== null) {
+ let p = document.createElement('p');
+ li.appendChild(p)
+ p.appendChild(document.createTextNode('Licensvillkor: '));
+ const t = document.createTextNode(x.license.name);
+ if (x.license.url === undefined || x.license.url === null) {
+ p.appendChild(t);
+ } else {
+ const a = document.createElement('a');
+ a.href = x.license.url;
+ a.target = '_blank';
+ a.appendChild(t);
+ p.appendChild(a);
+ }
+ }
+
+ if (x.product_url !== undefined && x.product_url !== null) {
+ let p = document.createElement('p');
+ li.appendChild(p)
+ const t = document.createTextNode('Produktlänk ');
+ const i = document.createElement('i');
+ i.classList.add('bi', 'bi-box-arrow-up-right');
+ const a = document.createElement('a');
+ a.href = x.product_url;
+ a.target = '_blank';
+ a.appendChild(t);
+ a.appendChild(i);
+ p.appendChild(a);
+ }
+
+ if (x.last_modified !== undefined && x.last_modified !== null) {
+ const p = document.createElement('p');
+ p.classList.add('small', 'text-muted');
+ li.appendChild(p);
+ const i = document.createElement('i');
+ i.classList.add('bi', 'bi-file-earmark-code');
+ p.appendChild(i);
+ p.appendChild(document.createTextNode(' '));
+ const t0 = document.createTextNode('Källfil');
+ if (x.url === undefined || x.url === null) {
+ p.appendChild(t0);
+ } else {
+ const a = document.createElement('a');
+ p.appendChild(a);
+ const i = document.createElement('i');
+ i.classList.add('bi', 'bi-box-arrow-up-right');
+ a.appendChild(t0);
+ a.appendChild(document.createTextNode(' '));
+ a.appendChild(i);
+ a.href = x.url;
+ a.target = '_blank';
+ }
+ const t1 = document.createTextNode(' ändrades senast ');
+ p.appendChild(t1);
+ const d = new Date(x.last_modified);
+ const td = document.createTextNode(d.toLocaleDateString('sv-SE'));
+ p.appendChild(td);
+ const t2 = document.createTextNode('.')
+ p.appendChild(t2);
+ }
+ });
+ });
+ });
+ });
};
})();
@@ -3270,6 +3449,7 @@ const [vectorLayers, featureOverlayLayer] = (function() {
/* layer selection panel */
+const infoMetadataAccordions = [];
(function() {
const modal = document.getElementById('layer-selection-panel');
modal.classList.add('modal');
@@ -3502,6 +3682,53 @@ const [vectorLayers, featureOverlayLayer] = (function() {
location.hash = '#' + searchParams.toString();
};
})();
+
+ (function() {
+ const accordion = document.getElementById('info-accordion');
+ layerHierarchy.forEach(function(x, idx) {
+ const item = document.createElement('div');
+ accordion.appendChild(item);
+ item.classList.add('accordion-item');
+
+ const header = document.createElement('div');
+ item.appendChild(header);
+ header.classList.add('accordion-header');
+
+ const btn = document.createElement('button');
+ header.appendChild(btn);
+
+ const collapse = document.createElement('div');
+ item.appendChild(collapse);
+ collapse.id = 'info-accordion-collapse-' + idx;
+ collapse.classList.add('accordion-collapse', 'collapse');
+
+ btn.type = 'button';
+ btn.setAttribute('data-bs-toggle', 'collapse');
+ btn.setAttribute('data-bs-target', '#' + collapse.id);
+ btn.setAttribute('aria-expanded', 'false');
+ btn.setAttribute('aria-controls', collapse.id);
+ btn.classList.add('accordion-button', 'collapsed');
+
+ const t = document.createTextNode(x.text);
+ btn.appendChild(t);
+
+ const body = document.createElement('div');
+ body.classList.add('accordion-body');
+ collapse.appendChild(body);
+
+ const ul = document.createElement('ul');
+ ul.classList.add('list-group', 'list-group-flush');
+ body.appendChild(ul);
+
+ infoMetadataAccordions.push({
+ element: ul,
+ items: x._layers.map(function(k) {
+ const groupname = k.split('_', 1)[0];
+ return [ groupname, k.slice(groupname.length + 1) ];
+ }),
+ });
+ });
+ })();
})();
/* legend panel */
diff --git a/style.css b/style.css
index 273c213..cb675a3 100644
--- a/style.css
+++ b/style.css
@@ -278,9 +278,60 @@ body.inprogress {
-webkit-user-select: text;
-moz-user-select: text;
user-select: text;
+ --modal-info-padding-x: .5rem;
+ --modal-info-bg-light: rgba(0, 0, 0, .08);
}
-#modal-info .modal-body ul > li {
- padding: 0.05rem 0;
+#modal-info .list-group-item,
+#modal-info {
+ --bs-list-group-border-width: 1px;
+}
+#modal-info .accordion {
+ --bs-accordion-active-bg: var(--bs-accordion-bg);
+ --bs-accordion-active-color: var(--bs-body-color);
+ --bs-accordion-btn-padding-x: .5rem;
+ --bs-accordion-btn-padding-y: .025rem;
+ --bs-accordion-btn-focus-box-shadow: none;
+ --bs-accordion-body-padding-x: var(--modal-info-padding-x);
+ --bs-accordion-body-padding-y: 0;
+ --bs-accordion-btn-active-bg: var(--modal-info-bg-light);
+ margin: 0 calc(var(--bs-accordion-btn-padding-x)*-1);
+}
+#modal-info .accordion-item {
+ border: none;
+}
+#modal-info .accordion-header > .accordion-button[aria-expanded="false"]:hover {
+ background-color: rgb(from var(--modal-info-bg-light) r g b / calc(alpha*.4));
+}
+#modal-info .accordion-header > .accordion-button[aria-expanded="true"] {
+ background-color: var(--bs-accordion-btn-active-bg);
+}
+#modal-info ul.list-group > li.list-group-item {
+ padding: .3rem var(--modal-info-padding-x);
+ margin: 0 calc(var(--modal-info-padding-x)*-1);
+ border: none;
+}
+#modal-info ul.list-group > li.list-group-item:not(:first-child) {
+ border-top: var(--bs-list-group-border-width) solid var(--modal-info-bg-light);
+}
+#info-body > ul.list-group > li.list-group-item:last-child,
+#info-accordion > .accordion-item:not(:last-child) ul.list-group > li.list-group-item:last-child {
+ border-bottom: var(--bs-list-group-border-width) solid var(--modal-info-bg-light);
+}
+#modal-info .modal-body ul.list-group > li.list-group-item:not(.text-muted):hover {
+ background-color: rgb(from var(--modal-info-bg-light) r g b / calc(alpha*.4));
+}
+#info-body {
+ padding-top: 0;
+ padding-bottom: 0;
+}
+#info-body > ul.list-group > li.list-group-item p,
+#modal-info .accordion-body ul.list-group > li.list-group-item p {
+ margin: .05rem 0 0 0;
+}
+#info-body > ul.list-group > li.list-group-item h6,
+#modal-info .accordion-body ul.list-group > li.list-group-item h6 {
+ margin: .05rem 0 0 0;
+ font-size: 1.15rem
}
#modal-info .modal-body a {
color: inherit;
@@ -290,6 +341,12 @@ body.inprogress {
opacity: .8;
text-decoration: underline;
}
+#modal-info .modal-body .info-credits {
+ margin: 0 calc(var(--modal-info-padding-x)*-1);
+ padding: .3rem var(--modal-info-padding-x);
+ margin-top: .3rem;
+ border-top: var(--bs-list-group-border-width) solid var(--modal-info-bg-light);
+}
.ol-overlaycontainer-stopevent .modal-backdrop.show {
pointer-events: auto;