1 OSM.HistoryChangesetsLayer = L.FeatureGroup.extend({
2 _getSidebarRelativeClassName: function ({ sidebarRelativePosition }) {
3 if (sidebarRelativePosition > 0) {
4 return "changeset-above-sidebar-viewport";
5 } else if (sidebarRelativePosition < 0) {
6 return "changeset-below-sidebar-viewport";
8 return "changeset-in-sidebar-viewport";
12 _getAreaStyle: function (changeset) {
16 className: this._getSidebarRelativeClassName(changeset)
20 _getBorderStyle: function (changeset) {
23 color: "var(--changeset-border-color)",
25 className: this._getSidebarRelativeClassName(changeset)
29 _getHighlightStyle: function (changeset) {
33 color: "var(--changeset-border-color)",
34 fillColor: "var(--changeset-fill-color)",
36 className: this._getSidebarRelativeClassName(changeset) + " changeset-highlighted"
40 updateChangesets: function (map, changesets) {
41 this._changesets = new Map(changesets.map(changeset => [changeset.id, changeset]));
42 this.updateChangesetShapes(map);
45 updateChangesetShapes: function (map) {
46 for (const changeset of this._changesets.values()) {
47 const bottomLeft = map.project(L.latLng(changeset.bbox.minlat, changeset.bbox.minlon)),
48 topRight = map.project(L.latLng(changeset.bbox.maxlat, changeset.bbox.maxlon)),
49 width = topRight.x - bottomLeft.x,
50 height = bottomLeft.y - topRight.y,
51 minSize = 20; // Min width/height of changeset in pixels
53 if (width < minSize) {
54 bottomLeft.x -= ((minSize - width) / 2);
55 topRight.x += ((minSize - width) / 2);
58 if (height < minSize) {
59 bottomLeft.y += ((minSize - height) / 2);
60 topRight.y -= ((minSize - height) / 2);
63 changeset.bounds = L.latLngBounds(map.unproject(bottomLeft),
64 map.unproject(topRight));
67 this.updateChangesetLocations(map);
68 this.reorderChangesets();
71 updateChangesetLocations: function (map) {
72 const mapCenterLng = map.getCenter().lng;
74 for (const changeset of this._changesets.values()) {
75 const changesetSouthWest = changeset.bounds.getSouthWest();
76 const changesetNorthEast = changeset.bounds.getNorthEast();
77 const changesetCenterLng = (changesetSouthWest.lng + changesetNorthEast.lng) / 2;
78 const shiftInWorldCircumferences = Math.round((changesetCenterLng - mapCenterLng) / 360);
80 if (shiftInWorldCircumferences) {
81 changesetSouthWest.lng -= shiftInWorldCircumferences * 360;
82 changesetNorthEast.lng -= shiftInWorldCircumferences * 360;
84 this._areaLayer.getLayer(changeset.id)?.setBounds(changeset.bounds);
85 this._borderLayer.getLayer(changeset.id)?.setBounds(changeset.bounds);
86 this._highlightLayer.getLayer(changeset.id)?.setBounds(changeset.bounds);
91 reorderChangesets: function () {
92 const changesetEntries = [...this._changesets];
93 changesetEntries.sort(([, a], [, b]) => {
94 const aInViewport = !a.sidebarRelativePosition;
95 const bInViewport = !b.sidebarRelativePosition;
96 if (aInViewport !== bInViewport) return aInViewport - bInViewport;
97 return b.bounds.getSize() - a.bounds.getSize();
99 this._changesets = new Map(changesetEntries);
101 this._areaLayer.clearLayers();
102 this._borderLayer.clearLayers();
103 this._highlightLayer.clearLayers();
105 for (const changeset of this._changesets.values()) {
106 const rect = L.rectangle(changeset.bounds, this._getAreaStyle(changeset));
107 rect.id = changeset.id;
108 rect.addTo(this._areaLayer);
111 for (const changeset of this._changesets.values()) {
112 const rect = L.rectangle(changeset.bounds, this._getBorderStyle(changeset));
113 rect.id = changeset.id;
114 rect.addTo(this._borderLayer);
118 toggleChangesetHighlight: function (id, state) {
119 const changeset = this._changesets.get(id);
120 if (!changeset) return;
122 let highlightRect = this._highlightLayer.getLayer(id);
123 if (!state && highlightRect) {
124 this._highlightLayer.removeLayer(highlightRect);
126 if (state && !highlightRect) {
127 highlightRect = L.rectangle(changeset.bounds, this._getHighlightStyle(changeset));
128 highlightRect.id = id;
129 this._highlightLayer.addLayer(highlightRect);
133 setChangesetSidebarRelativePosition: function (id, state) {
134 const changeset = this._changesets.get(id);
135 if (!changeset) return;
136 changeset.sidebarRelativePosition = state;
140 OSM.HistoryChangesetsLayer.addInitHook(function () {
141 this._changesets = new Map;
143 this._areaLayer = L.featureGroup().addTo(this);
144 this._borderLayer = L.featureGroup().addTo(this);
145 this._highlightLayer = L.featureGroup().addTo(this);
147 this._areaLayer.getLayerId = (layer) => layer.id;
148 this._borderLayer.getLayerId = (layer) => layer.id;
149 this._highlightLayer.getLayerId = (layer) => layer.id;