1 OSM.HistoryChangesetBboxLayer = L.FeatureGroup.extend({
2 getLayerId: function (layer) {
6 addChangesetLayer: function (changeset) {
7 const style = this._getChangesetStyle(changeset);
8 const rectangle = L.rectangle(changeset.bounds, {
12 text: OSM.i18n.t("javascripts.context.scroll_to_changeset"),
14 this.fire("requestscrolltochangeset", { id: changeset.id }, true);
22 rectangle.id = changeset.id;
23 return this.addLayer(rectangle);
26 updateChangesetLayerBounds: function (changeset) {
27 this.getLayer(changeset.id)?.setBounds(changeset.bounds);
30 _getSidebarRelativeClassName: function ({ sidebarRelativePosition }) {
31 if (sidebarRelativePosition > 0) {
32 return "changeset-above-sidebar-viewport";
33 } else if (sidebarRelativePosition < 0) {
34 return "changeset-below-sidebar-viewport";
36 return "changeset-in-sidebar-viewport";
41 OSM.HistoryChangesetBboxAreaLayer = OSM.HistoryChangesetBboxLayer.extend({
42 _getChangesetStyle: function (changeset) {
46 className: this._getSidebarRelativeClassName(changeset)
51 OSM.HistoryChangesetBboxOutlineLayer = OSM.HistoryChangesetBboxLayer.extend({
52 _getChangesetStyle: function (changeset) {
55 color: "var(--changeset-outline-color)",
57 className: this._getSidebarRelativeClassName(changeset)
62 OSM.HistoryChangesetBboxBorderLayer = OSM.HistoryChangesetBboxLayer.extend({
63 _getChangesetStyle: function (changeset) {
66 color: "var(--changeset-border-color)",
68 className: this._getSidebarRelativeClassName(changeset)
73 OSM.HistoryChangesetBboxHighlightAreaLayer = OSM.HistoryChangesetBboxLayer.extend({
74 _getChangesetStyle: function (changeset) {
78 fillColor: "var(--changeset-fill-color)",
80 className: this._getSidebarRelativeClassName(changeset)
85 OSM.HistoryChangesetBboxHighlightOutlineLayer = OSM.HistoryChangesetBboxLayer.extend({
86 _getChangesetStyle: function (changeset) {
89 weight: changeset.sidebarRelativePosition === 0 ? 8 : 6,
90 color: "var(--changeset-outline-color)",
92 className: this._getSidebarRelativeClassName(changeset) + " changeset-highlight-outline"
97 OSM.HistoryChangesetBboxHighlightBorderLayer = OSM.HistoryChangesetBboxLayer.extend({
98 _getChangesetStyle: function (changeset) {
102 color: "var(--changeset-border-color)",
104 className: this._getSidebarRelativeClassName(changeset)
109 OSM.HistoryChangesetsLayer = L.FeatureGroup.extend({
110 updateChangesets: function (map, changesets) {
111 this._changesets = new Map(changesets.map(changeset => [changeset.id, changeset]));
112 this.updateChangesetsGeometry(map);
115 updateChangesetsGeometry: function (map) {
116 const changesetSizeLowerBound = 20, // Min width/height of changeset in pixels
117 mapViewExpansion = 2; // Half of bbox border+outline width in pixels
119 const mapViewCenterLng = map.getCenter().lng,
120 mapViewPixelBounds = map.getPixelBounds();
122 mapViewPixelBounds.min.x -= mapViewExpansion;
123 mapViewPixelBounds.min.y -= mapViewExpansion;
124 mapViewPixelBounds.max.x += mapViewExpansion;
125 mapViewPixelBounds.max.y += mapViewExpansion;
127 for (const changeset of this._changesets.values()) {
128 const changesetNorthWestLatLng = L.latLng(changeset.bbox.maxlat, changeset.bbox.minlon),
129 changesetSouthEastLatLng = L.latLng(changeset.bbox.minlat, changeset.bbox.maxlon),
130 changesetCenterLng = (changesetNorthWestLatLng.lng + changesetSouthEastLatLng.lng) / 2,
131 shiftInWorldCircumferences = Math.round((changesetCenterLng - mapViewCenterLng) / 360);
133 if (shiftInWorldCircumferences) {
134 changesetNorthWestLatLng.lng -= shiftInWorldCircumferences * 360;
135 changesetSouthEastLatLng.lng -= shiftInWorldCircumferences * 360;
138 const changesetMinCorner = map.project(changesetNorthWestLatLng),
139 changesetMaxCorner = map.project(changesetSouthEastLatLng),
140 changesetSizeX = changesetMaxCorner.x - changesetMinCorner.x,
141 changesetSizeY = changesetMaxCorner.y - changesetMinCorner.y;
143 if (changesetSizeX < changesetSizeLowerBound) {
144 changesetMinCorner.x -= (changesetSizeLowerBound - changesetSizeX) / 2;
145 changesetMaxCorner.x += (changesetSizeLowerBound - changesetSizeX) / 2;
148 if (changesetSizeY < changesetSizeLowerBound) {
149 changesetMinCorner.y -= (changesetSizeLowerBound - changesetSizeY) / 2;
150 changesetMaxCorner.y += (changesetSizeLowerBound - changesetSizeY) / 2;
153 changeset.bounds = L.latLngBounds(map.unproject(changesetMinCorner),
154 map.unproject(changesetMaxCorner));
156 const changesetPixelBounds = L.bounds(changesetMinCorner, changesetMaxCorner);
158 changeset.hasEdgesInMapView = changesetPixelBounds.overlaps(mapViewPixelBounds) &&
159 !changesetPixelBounds.contains(mapViewPixelBounds);
162 this.updateChangesetsOrder();
165 updateChangesetsOrder: function () {
166 const changesetEntries = [...this._changesets];
167 changesetEntries.sort(([, a], [, b]) => b.bounds.getSize() - a.bounds.getSize());
168 this._changesets = new Map(changesetEntries);
170 for (const layer of this._bboxLayers) {
174 for (const changeset of this._changesets.values()) {
175 if (changeset.sidebarRelativePosition !== 0 && changeset.hasEdgesInMapView) {
176 this._areaLayer.addChangesetLayer(changeset);
180 for (const changeset of this._changesets.values()) {
181 if (changeset.sidebarRelativePosition === 0 && changeset.hasEdgesInMapView) {
182 this._areaLayer.addChangesetLayer(changeset);
186 for (const changeset of this._changesets.values()) {
187 if (changeset.sidebarRelativePosition !== 0) {
188 this._borderLayer.addChangesetLayer(changeset);
192 for (const changeset of this._changesets.values()) {
193 if (changeset.sidebarRelativePosition === 0) {
194 this._outlineLayer.addChangesetLayer(changeset);
198 for (const changeset of this._changesets.values()) {
199 if (changeset.sidebarRelativePosition === 0) {
200 this._borderLayer.addChangesetLayer(changeset);
205 toggleChangesetHighlight: function (id, state) {
206 const changeset = this._changesets.get(id);
207 if (!changeset) return;
209 this._highlightAreaLayer.clearLayers();
210 this._highlightOutlineLayer.clearLayers();
211 this._highlightBorderLayer.clearLayers();
214 this._highlightAreaLayer.addChangesetLayer(changeset);
215 this._highlightOutlineLayer.addChangesetLayer(changeset);
216 this._highlightBorderLayer.addChangesetLayer(changeset);
220 setChangesetSidebarRelativePosition: function (id, state) {
221 const changeset = this._changesets.get(id);
222 if (!changeset) return;
223 changeset.sidebarRelativePosition = state;
227 OSM.HistoryChangesetsLayer.addInitHook(function () {
228 this._changesets = new Map;
231 this._areaLayer = new OSM.HistoryChangesetBboxAreaLayer().addTo(this),
232 this._outlineLayer = new OSM.HistoryChangesetBboxOutlineLayer().addTo(this),
233 this._borderLayer = new OSM.HistoryChangesetBboxBorderLayer().addTo(this),
234 this._highlightAreaLayer = new OSM.HistoryChangesetBboxHighlightAreaLayer().addTo(this),
235 this._highlightOutlineLayer = new OSM.HistoryChangesetBboxHighlightOutlineLayer().addTo(this),
236 this._highlightBorderLayer = new OSM.HistoryChangesetBboxHighlightBorderLayer().addTo(this)