PageSourceSearch

https://satcar.dk/templates/satcar/js/mapbox-gl/src/ui/control/attribution_control

js satcar.dk collected 2026-10-02 01:54:10 UTC 6,350 bytes, 188 lines download raw bytes

1// @flow
2
3import DOM from '../../util/dom';
4import {bindAll} from '../../util/util';
5import config from '../../util/config';
6
7import type Map from '../map';
8
9type Options = {
10    compact?: boolean,
11    customAttribution?: string | Array<string>
12};
13
14/**
15 * An `AttributionControl` control presents the map's [attribution information](https://www.mapbox.com/help/attribution/).
16 *
17 * @implements {IControl}
18 * @param {Object} [options]
19 * @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.
20 * @param {string | Array<string>} [options.customAttribution] String or strings to show in addition to any other attributions.
21 * @example
22 * var map = new mapboxgl.Map({attributionControl: false})
23 *     .addControl(new mapboxgl.AttributionControl({
24 *         compact: true
25 *     }));
26 */
27class AttributionControl {
28    options: Options;
29    _map: Map;
30    _container: HTMLElement;
31    _innerContainer: HTMLElement;
32    _editLink: ?HTMLAnchorElement;
33    _attribHTML: string;
34    styleId: string;
35    styleOwner: string;
36
37    constructor(options: Options = {}) {
38        this.options = options;
39
40        bindAll([
41            '_updateEditLink',
42            '_updateData',
43            '_updateCompact'
44        ], this);
45    }
46
47    getDefaultPosition() {
48        return 'bottom-right';
49    }
50
51    onAdd(map: Map) {
52        const compact = this.options && this.options.compact;
53
54        this._map = map;
55        this._container = DOM.create('div', 'mapboxgl-ctrl mapboxgl-ctrl-attrib');
56        this._innerContainer = DOM.create('div', 'mapboxgl-ctrl-attrib-inner', this._container);
57
58        if (compact) {
59            this._container.classList.add('mapboxgl-compact');
60        }
61
62        this._updateAttributions();
63        this._updateEditLink();
64
65        this._map.on('styledata', this._updateData);
66        this._map.on('sourcedata', this._updateData);
67        this._map.on('moveend', this._updateEditLink);
68
69        if (compact === undefined) {
70            this._map.on('resize', this._updateCompact);
71            this._updateCompact();
72        }
73
74        return this._container;
75    }
76
77    onRemove() {
78        DOM.remove(this._container);
79
80        this._map.off('styledata', this._updateData);
81        this._map.off('sourcedata', this._updateData);
82        this._map.off('moveend', this._updateEditLink);
83        this._map.off('resize', this._updateCompact);
84
85        this._map = (undefined: any);
86    }
87
88    _updateEditLink() {
89        let editLink = this._editLink;
90        if (!editLink) {
91            editLink = this._editLink = (this._container.querySelector('.mapbox-improve-map'): any);
92        }
93
94        const params = [
95            {key: "owner", value: this.styleOwner},
96            {key: "id", value: this.styleId},
97            {key: "access_token", value: this._map._requestManager._customAccessToken || config.ACCESS_TOKEN}
98        ];
99
100        if (editLink) {
101            const paramString = params.reduce((acc, next, i) => {
102                if (next.value) {
103                    acc += `${next.key}=${next.value}${i < params.length - 1 ? '&' : ''}`;
104                }
105                return acc;
106            }, `?`);
107            editLink.href = `${config.FEEDBACK_URL}/${paramString}${this._map._hash ? this._map._hash.getHashString(true) : ''}`;
108            editLink.rel = "noopener nofollow";
109        }
110    }
111
112    _updateData(e: any) {
113        if (e && (e.sourceDataType === 'metadata' || e.dataType === 'style')) {
114            this._updateAttributions();
115            this._updateEditLink();
116        }
117    }
118
119    _updateAttributions() {
120        if (!this._map.style) return;
121        let attributions: Array<string> = [];
122        if (this.options.customAttribution) {
123            if (Array.isArray(this.options.customAttribution)) {
124                attributions = attributions.concat(
125                    this.options.customAttribution.map(attribution => {
126                        if (typeof attribution !== 'string') return '';
127                        return attribution;
128                    })
129                );
130            } else if (typeof this.options.customAttribution === 'string') {
131                attributions.push(this.options.customAttribution);
132            }
133        }
134
135        if (this._map.style.stylesheet) {
136            const stylesheet: any = this._map.style.stylesheet;
137            this.styleOwner = stylesheet.owner;
138            this.styleId = stylesheet.id;
139        }
140
141        const sourceCaches = this._map.style.sourceCaches;
142        for (const id in sourceCaches) {
143            const sourceCache = sourceCaches[id];
144            if (sourceCache.used) {
145                const source = sourceCache.getSource();
146                if (source.attribution && attributions.indexOf(source.attribution) < 0) {
147                    attributions.push(source.attribution);
148                }
149            }
150        }
151
152        // remove any entries that are substrings of another entry.
153        // first sort by length so that substrings come first
154        attributions.sort((a, b) => a.length - b.length);
155        attributions = attributions.filter((attrib, i) => {
156            for (let j = i + 1; j < attributions.length; j++) {
157                if (attributions[j].indexOf(attrib) >= 0) { return false; }
158            }
159            return true;
160        });
161
162        // check if attribution string is different to minimize DOM changes
163        const attribHTML = attributions.join(' | ');
164        if (attribHTML === this._attribHTML) return;
165
166        this._attribHTML = attribHTML;
167
168        if (attributions.length) {
169            this._innerContainer.innerHTML = attribHTML;
170            this._container.classList.remove('mapboxgl-attrib-empty');
171        } else {
172            this._container.classList.add('mapboxgl-attrib-empty');
173        }
174        // remove old DOM node from _editLink
175        this._editLink = null;
176    }
177
178    _updateCompact() {
179        if (this._map.getCanvasContainer().offsetWidth <= 640) {
180            this._container.classList.add('mapboxgl-compact');
181        } else {
182            this._container.classList.remove('mapboxgl-compact');
183        }
184    }
185
186}
187
188export default AttributionControl;

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.