84 lines
3.9 KiB
JavaScript
84 lines
3.9 KiB
JavaScript
// useMapAttribution.js — the data-credit line every map MUST carry.
|
|
//
|
|
// import { addMapAttribution } from '@map/composables/useMapAttribution'
|
|
// addMapAttribution(map, { boundaries: true })
|
|
//
|
|
// ═══ WHY THIS EXISTS — IT IS A LICENCE OBLIGATION, NOT A NICETY ═════════════
|
|
// Every map in this repo constructs Mapbox with `attributionControl: false`
|
|
// (useMapInstance.js and all three research profiles), and NOTHING replaced it. So
|
|
// the live maps were rendering NO attribution at all — not for geoBoundaries, and
|
|
// not for Mapbox/OpenStreetMap either, whose terms also require it.
|
|
//
|
|
// geoBoundaries' own request, verbatim: "we ask that you put the name
|
|
// 'geoBoundaries' with a link back to this website, www.geoboundaries.org,
|
|
// somewhere prominent on the page that uses the boundaries."
|
|
//
|
|
// gbOpen is ALSO a MIXED-LICENCE collection — it passes through each country's
|
|
// upstream licence, verified live against their API:
|
|
// India ADM1 CC BY 2.5 IN (source: github.com/datameet/maps)
|
|
// Sudan ADM0 CC BY 3.0 IGO (source: HDX)
|
|
// Brazil ADM0 CC BY 3.0 IGO (source: HDX)
|
|
// USA ADM0 Public Domain (US Census)
|
|
// China ADM0 Public Domain (Wikimedia Commons)
|
|
// Several therefore carry a genuine per-country attribution requirement. A repo
|
|
// comment previously called this "Apache-2.0-ish", which is wrong and would be the
|
|
// wrong basis for a publication decision.
|
|
//
|
|
// SELF-HOSTED, NO NETWORK. This is plain DOM + inline style: it adds no request, so
|
|
// it cannot leak a viewer's IP the way a third-party badge would. That matters here
|
|
// — see the open OPEN_DEFECT_mapbox_cdn finding.
|
|
|
|
const LINKS = {
|
|
boundaries: {
|
|
label: 'geoBoundaries',
|
|
href: 'https://www.geoboundaries.org',
|
|
title: 'Country and administrative boundaries — geoBoundaries gbOpen (mixed upstream licences; see docs)',
|
|
},
|
|
mapbox: { label: 'Mapbox', href: 'https://www.mapbox.com/about/maps/' },
|
|
osm: { label: '© OpenStreetMap', href: 'https://www.openstreetmap.org/copyright' },
|
|
};
|
|
|
|
/**
|
|
* Add the bottom-right attribution bar to a Mapbox map.
|
|
*
|
|
* @param {Object} map a mapboxgl.Map
|
|
* @param {Object} [opts]
|
|
* @param {boolean} [opts.boundaries=true] credit geoBoundaries (set false only if
|
|
* the map draws NO gb polygons at all)
|
|
* @param {boolean} [opts.basemap=true] credit Mapbox + OpenStreetMap
|
|
*/
|
|
export function addMapAttribution(map, opts = {}) {
|
|
if (!map || typeof map.addControl !== 'function') return null;
|
|
const { boundaries = true, basemap = true } = opts;
|
|
|
|
const el = document.createElement('div');
|
|
el.className = 'doxa-attribution mapboxgl-ctrl';
|
|
// Inline style: these maps live in SHADOW ROOTS, so a stylesheet in the host page
|
|
// would not reach here. Kept muted and small so it reads as a credit line, not UI.
|
|
el.style.cssText = [
|
|
'font:11px/1.45 system-ui,-apple-system,Segoe UI,Roboto,sans-serif',
|
|
'background:rgba(255,255,255,.82)', 'color:#3a4048',
|
|
'padding:2px 6px', 'border-radius:3px 0 0 0',
|
|
'pointer-events:auto', 'max-width:min(92vw,420px)',
|
|
].join(';');
|
|
|
|
const parts = [];
|
|
if (boundaries) parts.push(LINKS.boundaries);
|
|
if (basemap) { parts.push(LINKS.mapbox); parts.push(LINKS.osm); }
|
|
|
|
el.innerHTML = parts.map((p) =>
|
|
`<a href="${p.href}" target="_blank" rel="noopener noreferrer"`
|
|
+ (p.title ? ` title="${p.title}"` : '')
|
|
+ ` style="color:#2a5d8f;text-decoration:none">${p.label}</a>`).join(' · ');
|
|
|
|
const control = {
|
|
onAdd: () => el,
|
|
onRemove: () => { el.parentNode && el.parentNode.removeChild(el); },
|
|
getDefaultPosition: () => 'bottom-right',
|
|
};
|
|
map.addControl(control, 'bottom-right');
|
|
return control;
|
|
}
|
|
|
|
/** The same credit as plain text — for posters, PDFs and print, which have no DOM. */
|
|
export const ATTRIBUTION_TEXT = 'Boundaries: geoBoundaries (geoboundaries.org) · © Mapbox © OpenStreetMap';
|