/
attribution_control.js
118 lines (94 loc) · 3.62 KB
/
attribution_control.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
'use strict';
const DOM = require('../../util/dom');
const util = require('../../util/util');
/**
* An `AttributionControl` control presents the map's [attribution information](https://www.mapbox.com/help/attribution/).
*
* @implements {IControl}
* @param {Object} [options]
* @param {boolean} [options.compact] If `true` force a compact attribution that shows the full attribution on mouse hover, or if `false` force the full attribution control. The default is a responsive attribution that collapses when the map is less than 640 pixels wide.
* @example
* var map = new mapboxgl.Map({attributionControl: false})
* .addControl(new mapboxgl.AttributionControl({
* compact: true
* }));
*/
class AttributionControl {
constructor(options) {
this.options = options;
util.bindAll([
'_updateEditLink',
'_updateData',
'_updateCompact'
], this);
}
getDefaultPosition() {
return 'bottom-right';
}
onAdd(map) {
const compact = this.options && this.options.compact;
this._map = map;
this._container = DOM.create('div', 'mapboxgl-ctrl mapboxgl-ctrl-attrib');
if (compact) {
this._container.classList.add('compact');
}
this._updateAttributions();
this._updateEditLink();
this._map.on('sourcedata', this._updateData);
this._map.on('moveend', this._updateEditLink);
if (compact === undefined) {
this._map.on('resize', this._updateCompact);
this._updateCompact();
}
return this._container;
}
onRemove() {
this._container.parentNode.removeChild(this._container);
this._map.off('sourcedata', this._updateData);
this._map.off('moveend', this._updateEditLink);
this._map.off('resize', this._updateCompact);
this._map = undefined;
}
_updateEditLink() {
if (!this._editLink) this._editLink = this._container.querySelector('.mapbox-improve-map');
if (this._editLink) {
const center = this._map.getCenter();
this._editLink.href = `https://www.mapbox.com/map-feedback/#/${
center.lng}/${center.lat}/${Math.round(this._map.getZoom() + 1)}`;
}
}
_updateData(e) {
if (e && e.sourceDataType === 'metadata') {
this._updateAttributions();
this._updateEditLink();
}
}
_updateAttributions() {
if (!this._map.style) return;
let attributions = [];
const sourceCaches = this._map.style.sourceCaches;
for (const id in sourceCaches) {
const source = sourceCaches[id].getSource();
if (source.attribution && attributions.indexOf(source.attribution) < 0) {
attributions.push(source.attribution);
}
}
// remove any entries that are substrings of another entry.
// first sort by length so that substrings come first
attributions.sort((a, b) => a.length - b.length);
attributions = attributions.filter((attrib, i) => {
for (let j = i + 1; j < attributions.length; j++) {
if (attributions[j].indexOf(attrib) >= 0) { return false; }
}
return true;
});
this._container.innerHTML = attributions.join(' | ');
// remove old DOM node from _editLink
this._editLink = null;
}
_updateCompact() {
const compact = this._map.getCanvasContainer().offsetWidth <= 640;
this._container.classList[compact ? 'add' : 'remove']('compact');
}
}
module.exports = AttributionControl;