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, style);
9 rectangle.id = changeset.id;
10 return this.addLayer(rectangle);
13 updateChangesetLayerBounds: function (changeset) {
14 this.getLayer(changeset.id)?.setBounds(changeset.bounds);
17 _getSidebarRelativeClassName: function ({ sidebarRelativePosition }) {
18 if (sidebarRelativePosition > 0) {
19 return "changeset-above-sidebar-viewport";
20 } else if (sidebarRelativePosition < 0) {
21 return "changeset-below-sidebar-viewport";
23 return "changeset-in-sidebar-viewport";
28 OSM.HistoryChangesetBboxAreaLayer = OSM.HistoryChangesetBboxLayer.extend({
29 _getChangesetStyle: function (changeset) {
33 className: this._getSidebarRelativeClassName(changeset)
38 OSM.HistoryChangesetBboxOutlineLayer = OSM.HistoryChangesetBboxLayer.extend({
39 _getChangesetStyle: function (changeset) {
42 color: "var(--changeset-outline-color)",
44 className: this._getSidebarRelativeClassName(changeset)
49 OSM.HistoryChangesetBboxBorderLayer = OSM.HistoryChangesetBboxLayer.extend({
50 _getChangesetStyle: function (changeset) {
53 color: "var(--changeset-border-color)",
55 className: this._getSidebarRelativeClassName(changeset)
60 OSM.HistoryChangesetBboxHighlightBackLayer = OSM.HistoryChangesetBboxLayer.extend({
61 _getChangesetStyle: function (changeset) {
65 color: "var(--changeset-outline-color)",
66 fillColor: "var(--changeset-fill-color)",
68 className: this._getSidebarRelativeClassName(changeset) + " changeset-highlighted"
73 OSM.HistoryChangesetBboxHighlightBorderLayer = OSM.HistoryChangesetBboxLayer.extend({
74 _getChangesetStyle: function (changeset) {
78 color: "var(--changeset-border-color)",
80 className: this._getSidebarRelativeClassName(changeset) + " changeset-highlighted"
85 OSM.HistoryChangesetsLayer = L.FeatureGroup.extend({
86 updateChangesets: function (map, changesets) {
87 this._changesets = new Map(changesets.map(changeset => [changeset.id, changeset]));
88 this.updateChangesetsGeometry(map);
91 updateChangesetsGeometry: function (map) {
92 const changesetSizeLowerBound = 20; // Min width/height of changeset in pixels
94 const mapViewCenterLng = map.getCenter().lng;
96 for (const changeset of this._changesets.values()) {
97 const changesetNorthWestLatLng = L.latLng(changeset.bbox.maxlat, changeset.bbox.minlon),
98 changesetSouthEastLatLng = L.latLng(changeset.bbox.minlat, changeset.bbox.maxlon),
99 changesetCenterLng = (changesetNorthWestLatLng.lng + changesetSouthEastLatLng.lng) / 2,
100 shiftInWorldCircumferences = Math.round((changesetCenterLng - mapViewCenterLng) / 360);
102 if (shiftInWorldCircumferences) {
103 changesetNorthWestLatLng.lng -= shiftInWorldCircumferences * 360;
104 changesetSouthEastLatLng.lng -= shiftInWorldCircumferences * 360;
107 const changesetMinCorner = map.project(changesetNorthWestLatLng),
108 changesetMaxCorner = map.project(changesetSouthEastLatLng),
109 changesetSizeX = changesetMaxCorner.x - changesetMinCorner.x,
110 changesetSizeY = changesetMaxCorner.y - changesetMinCorner.y;
112 if (changesetSizeX < changesetSizeLowerBound) {
113 changesetMinCorner.x -= (changesetSizeLowerBound - changesetSizeX) / 2;
114 changesetMaxCorner.x += (changesetSizeLowerBound - changesetSizeX) / 2;
117 if (changesetSizeY < changesetSizeLowerBound) {
118 changesetMinCorner.y -= (changesetSizeLowerBound - changesetSizeY) / 2;
119 changesetMaxCorner.y += (changesetSizeLowerBound - changesetSizeY) / 2;
122 changeset.bounds = L.latLngBounds(map.unproject(changesetMinCorner),
123 map.unproject(changesetMaxCorner));
126 this.updateChangesetsOrder();
129 updateChangesetsOrder: function () {
130 const changesetEntries = [...this._changesets];
131 changesetEntries.sort(([, a], [, b]) => b.bounds.getSize() - a.bounds.getSize());
132 this._changesets = new Map(changesetEntries);
134 for (const layer of this._bboxLayers) {
138 for (const changeset of this._changesets.values()) {
139 if (changeset.sidebarRelativePosition !== 0) {
140 this._areaLayer.addChangesetLayer(changeset);
144 for (const changeset of this._changesets.values()) {
145 if (changeset.sidebarRelativePosition === 0) {
146 this._areaLayer.addChangesetLayer(changeset);
150 for (const changeset of this._changesets.values()) {
151 if (changeset.sidebarRelativePosition !== 0) {
152 this._borderLayer.addChangesetLayer(changeset);
156 for (const changeset of this._changesets.values()) {
157 if (changeset.sidebarRelativePosition === 0) {
158 this._outlineLayer.addChangesetLayer(changeset);
162 for (const changeset of this._changesets.values()) {
163 if (changeset.sidebarRelativePosition === 0) {
164 this._borderLayer.addChangesetLayer(changeset);
169 toggleChangesetHighlight: function (id, state) {
170 const changeset = this._changesets.get(id);
171 if (!changeset) return;
174 this._highlightBackLayer.addChangesetLayer(changeset);
175 this._highlightBorderLayer.addChangesetLayer(changeset);
177 this._highlightBackLayer.removeLayer(id);
178 this._highlightBorderLayer.removeLayer(id);
182 setChangesetSidebarRelativePosition: function (id, state) {
183 const changeset = this._changesets.get(id);
184 if (!changeset) return;
185 changeset.sidebarRelativePosition = state;
189 OSM.HistoryChangesetsLayer.addInitHook(function () {
190 this._changesets = new Map;
193 this._areaLayer = new OSM.HistoryChangesetBboxAreaLayer().addTo(this),
194 this._outlineLayer = new OSM.HistoryChangesetBboxOutlineLayer().addTo(this),
195 this._borderLayer = new OSM.HistoryChangesetBboxBorderLayer().addTo(this),
196 this._highlightBackLayer = new OSM.HistoryChangesetBboxHighlightBackLayer().addTo(this),
197 this._highlightBorderLayer = new OSM.HistoryChangesetBboxHighlightBorderLayer().addTo(this)